Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Convex backend development guidelines. Use when writing Convex functions, schemas, queries, mutations, actions, or any backend code in a Convex project. Triggers on tasks involving Convex database operations, real-time subscriptions, file storage, or serverless functions.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 25% | 0% |
Comprehensive guide for building Convex backends with TypeScript. Covers function syntax, validators, schemas, queries, mutations, actions, scheduling, and file storage.
Reference these guidelines when:
| Category | Impact | Description | | ----------------- | -------- | --------------------------------------------- | | Function Syntax | CRITICAL | New function syntax with args/returns/handler | | Validators | CRITICAL | Type-safe argument and return validation | | Schema Design | HIGH | Table definitions, indexes, system fields | | Query Patterns | HIGH | Efficient data fetching with indexes | | Mutation Patterns | MEDIUM | Database writes, patch vs replace | | Action Patterns | MEDIUM | External API calls, Node.js runtime | | Scheduling | MEDIUM | Crons and delayed function execution | | File Storage | LOW | Blob storage and metadata |
typescript// Public functions (exposed to clients) import { query, mutation, action } from "./_generated/server"; // Internal functions (only callable from other Convex functions) import { internalQuery, internalMutation, internalAction, } from "./_generated/server";
typescriptexport const myFunction = query({ args: { name: v.string() }, returns: v.string(), handler: async (ctx, args) => { return "Hello " + args.name; }, });
| Type | Validator | Example | | -------- | --------------------------------- | ------------- | | String | v.string() | "hello" | | Number | v.number() | 3.14 | | Boolean | v.boolean() | true | | ID | v.id("tableName") | doc._id | | Array | v.array(v.string()) | ["a", "b"] | | Object | v.object({...}) | {name: "x"} | | Optional | v.optional(v.string()) | undefined | | Union | v.union(v.string(), v.number()) | "x" or 1 | | Literal | v.literal("status") | "status" | | Null | v.null() | null |
typescript// Public functions import { api } from "./_generated/api"; api.example.myQuery; // convex/example.ts → myQuery // Internal functions import { internal } from "./_generated/api"; internal.example.myInternalMutation;
typescript// Schema messages: defineTable({...}).index("by_channel", ["channelId"]) // Query await ctx.db .query("messages") .withIndex("by_channel", (q) => q.eq("channelId", channelId)) .order("desc") .take(10);
args and returns validators on all functionsv.null() for void returns - never omit return validatorwithIndex() not filter() - define indexes in schemainternalQuery/Mutation/Action for private functionsctx.db - use runQuery/runMutation insteadFor the complete guide with all rules and detailed code examples, see AGENTS.md.
Other measured skills in the registry, with their headline benchmark lift.