Skip to main content
Convex functions are the building blocks of your backend. There are three types of functions, each designed for specific use cases:
  • Queries - Read data from the database (reactive, transactional, fast)
  • Mutations - Write data to the database (transactional, atomic)
  • Actions - Interact with external services (non-transactional, can call APIs)

Queries

Queries are read-only functions that fetch data from your database. They’re reactive - when data changes, queries automatically re-run and update subscribed clients.

Basic query

Query context

Queries receive a context object with:
  • ctx.db - Read-only database access (GenericDatabaseReader)
  • ctx.auth - Current user authentication information
  • ctx.storage - Read-only access to stored files
  • ctx.runQuery - Call another query within the same transaction

Query characteristics

  • Read-only - Cannot modify the database
  • Reactive - Automatically re-run when data changes
  • Transactional - See a consistent snapshot of the database
  • Fast - Typically run in less than 10ms
  • Cached - Results can be cached by the client
Queries see a consistent snapshot of the database at a single point in time. All reads within a query are isolated from concurrent writes.

Mutations

Mutations modify data in your database. All writes within a mutation are atomic - either all succeed or all fail.

Basic mutation

Mutation context

Mutations receive a context object with:
  • ctx.db - Read-write database access (GenericDatabaseWriter)
  • ctx.auth - Current user authentication information
  • ctx.storage - Generate upload URLs and delete files
  • ctx.scheduler - Schedule functions to run later
  • ctx.runQuery - Call a query within the same transaction
  • ctx.runMutation - Call another mutation in a sub-transaction

Mutation characteristics

  • Read-write - Can read and modify the database
  • Atomic - All writes succeed or all fail (no partial states)
  • Isolated - Concurrent mutations don’t interfere with each other
  • Reactive triggers - Automatically updates subscribed queries
  • Optimistically retried - Automatically retried on conflicts
Mutations may be retried automatically if there are concurrent conflicts. Avoid non-idempotent side effects (like sending emails) in mutations. Use actions for external side effects instead.

Database write operations

Mutations can use four write operations:
1

Insert

Add new documents to a table:
2

Patch

Shallow merge updates (only specified fields change):
3

Replace

Completely replace a document:
4

Delete

Remove a document:

Actions

Actions are functions that can interact with external services and use Node.js APIs. Unlike queries and mutations, they don’t have direct database access.

Basic action

Action context

Actions receive a context object with:
  • ctx.runQuery - Run a query (separate read transaction)
  • ctx.runMutation - Run a mutation (separate write transaction)
  • ctx.runAction - Call another action
  • ctx.scheduler - Schedule functions to run later
  • ctx.auth - Current user authentication information
  • ctx.storage - Generate upload URLs and get file URLs
  • ctx.vectorSearch - Perform vector similarity searches
ctx.db is not available in actions. Use ctx.runQuery and ctx.runMutation to interact with the database.

Action characteristics

  • Non-transactional - Can make multiple separate database calls
  • External access - Can call third-party APIs and use Node.js libraries
  • No reactivity - Don’t automatically re-run when data changes
  • Longer timeout - Can run for several minutes (vs milliseconds for queries/mutations)
  • Environment variables - Can access process.env

When to use actions

Argument validation

All function types support argument validation using the args field:
For security, always add argument validation to public functions. This prevents users from passing unexpected or malicious input.

Return value validation

You can optionally validate return values:

Public vs internal functions

Functions can be public (callable from clients) or internal (only callable from other functions):
Use internal functions for:
  • Administrative operations
  • Functions called by scheduled jobs
  • Helper functions shared between other functions
  • Operations that should only run server-side

Calling functions

Functions call each other using generated references:

Function comparison

Next steps