convex-best-practices
Installation
SKILL.md
name: convex-best-practices description: Production patterns for Convex apps and the rules the @convex-dev/eslint-plugin enforces: validators, indexes, idempotent mutations, avoiding OCC conflicts, thin function wrappers, error handling. Use when reviewing Convex code, asking whether a pattern is right, setting up ESLint, or fixing write conflicts and slow queries.
Convex best practices
The patterns that keep a Convex app fast and correct in production. The rule that matters most: read as little as possible before you write, and read through an index.
Rules that matter most
- Validators on every function.
argsandreturns, withreturns: v.null()when nothing comes back. - Indexes, not filters. Every table read goes through
withIndexagainst an index inconvex/schema.ts. - Idempotent mutations. Return early when the document is already in the target state so retries are safe.
- Patch without reading first.
ctx.db.patch(id, fields)throws if the doc is missing; you rarely need the old value. Promise.allfor independent writes. Do not await them one at a time.- Schedule
internal.*only. Crons andctx.schedulerrun without a client, so public targets skip auth. - Thin wrappers. Auth and business logic live in plain helpers that take
ctx. ConvexErrorfor anything a client should read. PlainErrormessages are redacted in production.