Function types
For Node.js actions, see Node Actions. To integrate plain Convex functions (for use with Convex components or other libraries), see Plain Convex Functions.
Defining a spec
Each function spec defines the functionâs name, argument fields, and returns schema. The optionalargs callback returns a Schema.Struct field map and defaults to {} when omitted, while returns and the optional error are callbacks returning schemas. All provided callbacks are evaluated lazily the first time the function is invoked. Function specs are added to a GroupSpec and default-exported from a *.spec.ts file. See The Spec/Impl Model for a full walkthrough.
confect/notes.spec.ts
confect codegen after adding or changing specs.
Typed errors
A spec can also declare an optionalerror schema. When it does, the corresponding handlerâs Effect error channel is typed as that schema, and the failure is decoded for callers at every call site (React hooks, JS clients, and tests). See Error Handling for the full walkthrough.
Paginated queries
Define a paginated query withFunctionSpec.publicPaginatedQuery (or internalPaginatedQuery). Instead of returns, pass an item schemaâthe type of one element in a page. The optional args field map declares only your own arguments; Confect composes the Convex-facing schemas for you, adding the paginationOpts argument (with all of Convexâs pagination protocol fields) and wrapping item in a PaginationResult returns schema.
confect/notes.spec.ts
paginationOpts in argsâit is added automatically, and declaring it yourself is a type (and runtime) error.
The handler receives the decoded args including paginationOpts, which it typically forwards directly to paginate:
confect/notes.impl.ts
error schema like any other function. On the client, consume them with usePaginatedQuery.
Implementing functions
Each function impl contains a handler that implements the functionâs logic. Function impls are composed into group impls using Effect layers. The handler receives the decoded arguments as its first parameter and returns anEffect. Use the generated services (like DatabaseReader, DatabaseWriter, Auth, etc.) inside your handler to interact with Convex.
confect/notes.impl.ts
GroupImpl.finalize is the per-group completeness check: it only typechecks once every function declared by the spec has been provided to the group layer.
Convex bundles a deployment into a single artifact, but a functionâs cold
start only evaluates the module graph reachable from its entry point. Confect
emits one Convex module per group, so cold-starting a function only evaluates
its own groupâs spec, impl, and the tables it touches. To keep that cold start
fast, import Effect from its submodule paths (
import * as Schema from "effect/Schema") rather than the effect barrel in your confect/ filesâa
barrel import pulls the whole Schema namespace into the module graph your
function evaluates at cold start, even when you use only a small part of it.