Overview
Voltro's caching layer (@voltro/cache) — an always-on memory default, swappable Redis-compatible backends, a low-level wrap primitive, and automatic query-result invalidation.
Voltro ships a first-class cache in @voltro/cache. It is always on — the in-process memory backend is the zero-config default, so ctx.cache works in every handler from the first boot with nothing to install. You opt into a distributed backend (Redis & friends) only when you need cross-instance sharing.
There are two ways to use it, and they share one backend:
- Low-level —
ctx.cache.wrap(key, { ttl, tags }, () => compute())in any handler. Cache-aside with tags, stale-while-revalidate, and single-flight de-duplication. Use it for expensive derived work: aggregations, external-API enrichment, rendered fragments. - Automatic query caching — add a
cachefield to adefineQueryand the framework caches the server snapshot and invalidates it automatically when a mutation writes any table the query depends on. Zero manual busting.
The defining idea mirrors the rest of Voltro: the backend is a configuration choice, the code is identical. The same wrap call and the same cache: field run against the in-process map in dev and against Redis (or Valkey / KeyDB / Dragonfly / Upstash) in production — you flip CACHE_BACKEND, not your handlers.
// app.config.ts — memory (default) or redis
export default { type: 'api', name: 'myApi', store: 'postgres', cache: 'redis' }// any handler — works on every backend
export default async (input: { orgId: string }, ctx) =>
ctx.cache.wrap(
`dashboard:${input.orgId}`,
{ ttlMs: 60_000, tags: [`org:${input.orgId}`] },
async () => expensiveDashboard(ctx, input.orgId),
)What it is not
- Not the reactive query engine. Live
useSubscriptionqueries already stay fresh by pushing deltas — caching is for non-live derived work and for sharing a query's initial snapshot across many subscribers/instances. - Not a runtime plugin. A cache backend is infrastructure, so it's an
app.config+ baseline concern (voltro add redis), not aplugins:entry.
Where to go next
- Backends & engines — memory vs Redis, the five RESP-compatible engines, connection presets, env vars.
- Low-level
wrap—ctx.cache/ the EffectCacheservice, tags, SWR, single-flight. - Query caching — the
cache:field, thescopesecurity rule, auto-invalidation. - Durable key-value —
ctx.kv(durable, never evicted — for state you can't recompute): the full API, TTL, tenant namespacing. - Key-value backends —
database(durable) vsredisvsmemory, theKV_BACKENDselector, theKvStoreport, custom backends. - Named connections — the shared registry behind the cache / KV / rate limiter / broadcast, the
<NAME>_REDIS_URL→REDIS_URLscheme, and per-concern enablement. - Enabling Redis —
voltro add redis,create-project --cache=redis, thevoltro cacheCLI, the dashboard panel.