convex-best-practices
Guidelines for building production-ready Convex apps covering function organization, query patterns, validation, TypeScript usage, error handling, and the Zen of Convex design philosophy
By waynesutton · 3,758 installs
npx skills add waynesutton/convexskills --skill convex-best-practices
Source repository · Upstream listing
Convex Best Practices
Build production ready Convex applications by following established patterns for function organization, query optimization, validation, TypeScript usage, and error handling.
Code Quality
All patterns in this skill comply with @convex dev/eslint plugin . Install it for build time validation:
The plugin enforces four rules:
Rule What it enforces
no old registered function syntax Object syntax with handler
require argument validators args: {} on all functions
explicit table ids Table name in db operations
import wrong runtime No Node imports in Convex runtime
Docs: https://docs.convex.dev/eslint
Documentation Sources
Before implementing, do not assume; fetch the latest documentation:
Primary: https://docs.convex.dev/understanding/best practices/
Error Handling: https://docs.convex.dev/functions/error handling
Write Conflicts: https://docs.convex.dev/error 1
For broader context: https://docs.convex.dev/llms.txt
Instructions
The Zen of Convex
1. Convex manages the hard parts Let Convex handle caching, real time sync, and consistency
2. Functions are the API Design your functions as your application's interface
3. Schema is truth Define your data model explicitly in schema.ts
4. TypeScript everywhere Leverage end to end type safety
5. Queries are reactive Think in terms of subscriptions, not requests
Function Organization
Organize your Convex functions by domain:
Argument and Return Validation
Always define validators for arguments AND return types:
Query Patterns
Use indexes instead of filters for efficient queries:
Error Handling
Use ConvexError for user facing errors:
Avoiding Write Conflicts (Optimistic Concurrency Control)
Convex uses OCC. Follow these patterns to minimize conflicts:
TypeScript Best Practices
Internal vs Public Functions
Examples
Complete CRUD Pattern
Best Practices
Never run npx convex deploy unless explicitly instructed
Never run any git commands unless explicitly instructed
Always define return validators for functions
Use indexes for all queries that filter data
Make mutations idempotent to handle retries gracefully
Use ConvexError for user facing error messages
Organize functions by domain (users.ts, tasks.ts, etc.)
Use internal functions for sensitive operations
Leverage TypeScript's Id and Doc types
Common Pitfalls
1. Using filter instead of withIndex Always define indexes and use withIndex
2. Missing return validators Always specify the returns field
3. Non idempotent mutations Check current state before updating
4. Reading before patching unnecessarily Patch directly when possible
5. Not handling null returns Document IDs might not exist
References
Convex Documentation: https://docs.convex.dev/
Convex LLMs.txt: https://docs.convex.dev/llms.txt
Best Practices: https://docs.convex.dev/understanding/best practices/
Error Handling: https://docs.convex.dev/functions/error handling
Write Conflicts: https://docs.convex.dev/error 1