useQuery shares results across consumers and updates reactively. So what’s left to cache?
Three layers worth caching
Expensive third-party API responses
A weather API call, a slow LLM completion. Cache by content hash in a Convex table; check before re-fetching.
Computed aggregates
Daily / monthly metrics computed from millions of events. Materialize via scheduled functions; query the materialized table.
Static assets at the edge
Images, fonts, JS bundles. Vly’s CDN caches these by default with appropriate TTLs.
Browser storage for session-scoped data
User preferences, recently viewed items. localStorage / sessionStorage. Sync to Convex on important changes.
When NOT to cache
- Convex query results. Already cached. Layering a separate cache on top creates stale data bugs.
- Authenticated user info. Read from
useQuery(api.users.me); reactive sync keeps it fresh.
Patterns
LLM call cache
Materialized view
dailyMetrics (instant) instead of computing on-demand.
Invalidation
- Convex queries: automatic.
- LLM cache: TTL or content-hash mismatch.
- Materialized views: re-run on schedule or manual trigger.
- CDN: cache-busting via filename hash (vly handles this for built assets).
Related
Real-time sync
The free, automatic cache.
Scheduled functions
For periodic re-materialization.
Performance issues
When caching helps.
