Convex reactive database patterns, schema design, real-time queries, mutations, actions, and deployment best practices. Use when designing Convex schemas, writing queries/mutations, or managing the Convex backend.
100
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
For project-specific schema, functions, and deployment details, see database-config.md.
Function Registration
query/mutation/action; Private: internalQuery/internalMutation/internalAction (import from ./_generated/server)returns validator; use returns: v.null() when the function returns nothing (JS implicitly returns null)Function References
api.filename.functionName for public and internal.filename.functionName for internal functions (from ./_generated/api)ctx.runQuery/ctx.runMutation/ctx.runAction — always use function referencesQueries
.filter() — define an index in the schema and use .withIndex() instead.unique() for single document queries.delete() on queries — collect results, then call ctx.db.delete(row._id) on eachActions
"use node"; at the top of files containing actions that use Node.js built-in modulesctx.db inside actions — actions don't have database access; use ctx.runQuery/ctx.runMutation insteadSchema
["field1", "field2"] → "by_field1_and_field2"_id or _creationTime — they are automatic system fieldsGeneral
convex/schema.ts using defineSchema/defineTable.paginate() for large result setsId<'tableName'> for document ID types (from ./_generated/dataModel)v.null() not v.undefined() — undefined is not a valid Convex valueprocess.env in actions onlyimport { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
users: defineTable({
name: v.string(),
email: v.string(),
role: v.union(v.literal("admin"), v.literal("user")),
})
.index("by_email", ["email"])
.index("by_role", ["role"]),
});import { query } from "./_generated/server";
import { v } from "convex/values";
export const list = query({
args: { role: v.optional(v.string()) },
returns: v.array(v.any()),
handler: async (ctx, args) => {
if (args.role) {
return await ctx.db.query("users")
.withIndex("by_role", q => q.eq("role", args.role!))
.collect();
}
return await ctx.db.query("users").collect();
},
});import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const create = mutation({
args: { name: v.string(), email: v.string() },
returns: v.id("users"),
handler: async (ctx, args) => {
return await ctx.db.insert("users", { ...args, role: "user" });
},
});useQuery hook for automatic real-time subscriptionsuseMutation for optimistic updates.paginate()npx convex deploynpx convex dev for local development with hot reloadnpx convex import / npx convex export for data managementconvex/schema.ts and run npx convex dev locally; confirm the dev server starts and responds (checkpoint: http://localhost:8888 or the configured port). Run a small validation script or sample queries to verify schema changes (validation checkpoint).returns validators and unit test against the dev server.npx convex deploy to push the change to production.convex import/export), and run a quick smoke check against your app (example):curl -fsS https://<APP_URL>/health || (echo "health check failed" && exit 1)If an issue occurs: roll back via npx convex import of the last good export, fix locally, and re-deploy. After a rollback, re-run the same smoke check to confirm services are restored.
f5c8508
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.