home / skills / phrazzld / claude-config / convex-development

convex-development skill

/skills/convex-development

This skill helps you optimize Convex backends for cost, performance, and security by applying best practices across queries, schemas, and migrations.

npx playbooks add skill phrazzld/claude-config --skill convex-development

Review the files below or copy the command above to add this skill to your agents.

Files (8)
SKILL.md
2.7 KB
---
name: convex-development
description: |
  Apply Convex database best practices for cost optimization, performance, security, and architecture.
  Use when: building Convex backends, optimizing queries, handling embeddings/vector search,
  reviewing Convex code, designing schemas, planning migrations, or discussing Convex architecture.
  Keywords: Convex, real-time database, queries, mutations, actions, indexes, pagination,
  vector search, embeddings, schema, migrations, ctx.auth, convex-helpers, bandwidth.
effort: high
---

# Convex Development

Best practices for robust, secure, performant, cost-effective Convex backends.

## Core Principle

**Deep modules via the `convex/model/` pattern.** Most logic should be plain TypeScript; query/mutation wrappers should be thin.

```
convex/
  _generated/         # MUST commit to git!
  model/              # Business logic (testable, reusable)
  users.ts            # Public API (thin wrappers)
  schema.ts
```

## Critical Rules

1. **ALWAYS commit `convex/_generated/`** - Required for type-checking, CI/CD, team productivity
2. **Index what you query** - `.withIndex()` not `.filter()` for efficient queries
3. **Compound indexes for multi-field filters** - If querying `userId + status`, create index `["userId", "status"]` to filter at index level, not post-fetch
4. **Paginate everything** - Never unbounded `.collect()` on user-facing queries
5. **Trust `ctx.auth` only** - Never user-provided auth data

## Quick Reference

| Need | Use |
|------|-----|
| Read data reactively | `query` |
| Write to database | `mutation` |
| External APIs, vector search | `action` |
| Scheduled tasks | `internalMutation` / `internalAction` |

## Anti-Patterns Scanner

Run `scripts/anti_patterns_scanner.py ./convex` to detect common issues.

## Detailed References

For comprehensive guidance, see:
- `references/cost-mitigation.md` - Bandwidth optimization, indexing, pagination
- `references/embeddings-vectors.md` - Vector search patterns, co-location decisions
- `references/query-performance.md` - Compound indexes, query segmentation, caching
- `references/security-access.md` - Auth patterns, RLS, RBAC, convex-helpers
- `references/schema-migrations.md` - Expand/Contract pattern, environment management
- `references/architectural-patterns.md` - File organization, state machines, naming

## Philosophy

- **Cost First**: Bandwidth is often the largest cost. Index aggressively, paginate everything.
- **Security First**: Never trust client input. Always use `ctx.auth`.
- **Reactivity is Power**: Use `useQuery` for real-time updates; don't forfeit with one-off fetches.
- **Type Safety End-to-End**: Leverage Convex's full type chain from database to UI.

Overview

This skill applies Convex database best practices to optimize cost, performance, security, and architecture for production backends. It codifies patterns for schema design, queries, mutations, actions, indexing, pagination, and embeddings to keep systems efficient and maintainable. The guidance is practical, concrete, and geared toward teams building real-time apps with Convex.

How this skill works

The skill inspects Convex project structure and code to validate conventions like committing _generated/, thin public API wrappers, and a model/ layer for business logic. It highlights indexing opportunities, detects unbounded collections, flags auth anti-patterns, and advises where to run actions vs queries vs mutations. It also references patterns for vector search placement, schema migration strategy, and bandwidth/cost mitigation.

When to use it

  • When building a new Convex backend or reorganizing an existing one
  • When optimizing query performance or reducing bandwidth costs
  • When designing schema changes or planning migrations
  • When implementing embeddings or vector search patterns
  • When reviewing Convex code for security, auth, or best-practice compliance

Best practices

  • Commit convex/_generated/ to source control for type safety and CI stability
  • Keep public API files thin; put business logic in convex/model/ modules for testability
  • Index what you query: prefer .withIndex() and create compound indexes for multi-field filters
  • Paginate all user-facing queries; avoid unbounded .collect() to control bandwidth and costs
  • Trust server auth (ctx.auth) only; never accept client-provided auth or role data
  • Use actions for external API calls and vector search; keep queries reactive and mutations for writes

Example use cases

  • Run an anti-pattern scanner to find unindexed queries and unbounded collections before release
  • Design a compound index for frequent userId+status filters to shift filtering to the index layer
  • Move embedding lookup into an action and co-locate vectors to reduce cross-row reads and latency
  • Refactor mutation logic into model/ modules so unit tests can validate core business rules
  • Plan schema migrations using expand/contract patterns across environments to avoid downtime

FAQ

What should I commit to git for Convex?

Always commit convex/_generated/ so types remain consistent across CI and team members.

When should I use an action vs a query?

Use queries for reactive reads, mutations for database writes, and actions for external APIs, embedding/vector search, or long-running tasks.

How do I control bandwidth costs?

Index aggressively, paginate all user-facing queries, and avoid returning full collections with .collect(); optimize data shapes returned to clients.