useQuery(api.tasks.list, { teamId }), it receives the current results and gets pushed updates whenever those results would change.
How it works
No polling. No manual cache invalidation. Norefetch() calls.
Why it matters
Less code
A typical “live dashboard” is 50 lines of polling, debouncing, and stale-data handling. With reactive queries: zero.
Lower latency
Push, not pull. Updates arrive in under 100 ms after the underlying mutation commits.
Multi-user out of the box
Two users editing the same data see each other’s changes immediately. No extra plumbing.
Predictable cost
No “1-second polling × 10,000 users = 10k req/s” surprise bills.
Common patterns
- Live dashboard
- Collaborative editor
- Presence
- Real-time chat
A
useQuery for each chart. As underlying data flows in, the charts auto-update.Limits
- ~10,000 concurrent subscribers per query (soft; raisable)
- A query with very expensive computation will re-run on every relevant mutation; design queries to be cheap
- Subscriptions consume a small amount of bandwidth even when idle (~1 KB/s per active subscription)
Tips
Related
Convex queries
The function type that powers reactive sync.
Real-time sync patterns
Architectural patterns.
Real-time chat recipe
A worked example.
