Convex reactive database patterns, schema design, real-time queries, mutations, actions, authentication, migrations, performance optimization, and component creation. Use when designing Convex schemas, writing queries/mutations, managing the Convex backend, setting up auth, migrating data, optimizing performance, or building Convex components.
73
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Project-specific schema, functions, and deployment details: database-config.md. Official docs: https://docs.convex.dev/
Exceeding one of these fails the transaction, so design against them rather than discovering them:
| Limit | Value |
|---|---|
| Query/mutation execution time | 1 second (your code only, excludes DB operations) |
| Action execution time | 10 minutes |
| Data read / written | 16 MiB each |
| Documents scanned | 32,000 — includes documents .filter() discards |
| Index ranges read | 4,096 (each db.get and db.query counts) |
| Documents written | 16,000 |
| Function return value | 16 MiB |
Batch anything larger into a cursor-based self-scheduling internalMutation:
paginate({ cursor, numItems }), then ctx.scheduler.runAfter(0, internal.x.batch, { cursor: result.continueCursor }) while !result.isDone — or use the migrations
component.
Functions
query/mutation/action. Internal: internalQuery/internalMutation/internalAction. All from ./_generated/server.returns validator; use returns: v.null() when the function returns nothing (JS implicitly returns null).api.file.fn, internal.file.fn from ./_generated/api) to ctx.runQuery/runMutation/runAction — never the function itself.Queries
.filter(). Convex's .filter() performs the same as filtering in JS — neither pushes the predicate to storage. Only .withIndex()/.withSearchIndex() reduce documents scanned..delete(): collect results, then ctx.db.delete(row._id) per row..unique() for single-document reads.Mutations
ctx.db.patch() — an unchanged write still costs invalidation, replication, and trigger execution.Actions
ctx.db does not exist in actions — use ctx.runQuery/ctx.runMutation."use node"; at the top.Schema
["team", "user"] → by_team_and_user. Index fields must be queried in definition order._id or _creationTime — they are automatic system fields.by_team_and_user also serves by_team queries).v.null(), never v.undefined() — undefined is not a valid Convex value.Components
ctx.auth or process.env. Resolve both in the app and pass values across.v.string(), not v.id("parentTable").query/mutation/action from the component's own ./_generated/server.Environment
npx convex env set; read them with process.env in actions only.npx convex dev (long-running watcher, interactive on first run — ask the user to run it) → verify → npx convex deploy. If a deploy goes wrong, roll back by npx convex import of the last good export, fix locally, re-deploy.
| Step | Checkpoint |
|---|---|
| Schema change | npx convex dev starts without errors |
| Breaking change | checklist completed |
| Auth function | ctx.auth.getUserIdentity() non-null in test |
| Deploy | Smoke check passes; no npx convex insights regressions |
| Component | npx convex codegen succeeds |
fa0c341
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.