Defining an index
convex/schema.ts
by_<field> for single-column, by_<a>_and_<b> for compound.
Using an index
q chain inside withIndex matches the index’s column order.
When to add an index
✅ When you filter by it
.filter(t => t.field === value) is O(n). .withIndex(...) is O(log n).✅ When you sort by it
Sorted-order queries on indexed fields are free; on non-indexed, you read everything and sort in memory.
❌ For tiny tables
< 100 rows: no benefit. Don’t bother.
❌ Pre-emptively
Each index slightly slows writes. Add when a query is slow, not before.
Compound indexes follow query order
["teamId", "status"] accelerates queries that filter by teamId (or teamId + status together). It does not accelerate filtering by status alone.
For “filter by team OR by status independently,” create both indexes:
Built-in indexes
Every table has an implicit index on_id (the primary key) and _creationTime. So .order("desc").take(10) for “most recent 10” is always fast.
Inspecting query performance
vly’s editor flags slow queries in the console. For deeper inspection:Tips
Related
Schema
Index syntax.
Queries
Using indexes.
Performance issues
Debugging slow queries.
