Caching
Store expensive results once and serve them from memory or Redis with a type-safe API: cached values are the same model objects as the rest of your code. There is no separate cache client to set up.
Type-safe caching
Fetching the same rows on every request can be slow and expensive, but adding a cache usually means a separate client, another serialization format, and hand-written invalidation code. That invalidation code is where stale data and subtle bugs appear.
Serverpod ships a built-in caching system: a local in-memory cache, a priority cache for hot keys, and a distributed cache backed by Redis. They work with your Serverpod models, so cached values are the same type of objects you already pass around.
How it works
1Store a value
Put any serializable model into the cache, optionally with a lifetime.
await session.caches.local.put(
'product-$id',
product,
lifetime: Duration(minutes: 5),
);
2Read it back, or compute on a miss
On a miss, the handler runs, the value is cached, and the same value is returned.
var product = await session.caches.local.get(
'product-$id',
CacheMissHandler(
() async => Product.db.findById(session, id),
lifetime: Duration(minutes: 5),
),
);
3Invalidate when data changes
Remove the entry when the underlying data changes, so readers never see stale values.
await session.caches.local.invalidateKey('product-$id');
Local caches
An in-memory least-recently-used (LRU) cache for general use, plus a priority cache that keeps your hottest keys resident, both scoped per server.
Distributed cache
The same typed API, backed by Redis, gives every server in your cluster a shared cache for session data and expensive computed values.
var product = await session.caches.global.get<Product>('product-$id');
Type-safe values
You cache and read your own model objects, not untyped blobs, so a cached value is checked at compile time just like the objects you store in the database.
Everything included
Why Serverpod
Works with
Redis In-memory caching
Frequently asked questions
Does Serverpod support Redis?
Yes. The distributed cache is backed by Redis and shares entries across every server in your cluster.
Can I cache in memory without Redis?
Yes. The local and priority caches run in memory on each server and require no additional services.
What can I cache?
Any serializable Serverpod model, so cached values keep the same types as the rest of your code.
How does cache invalidation work?
Entries expire per-key using a TTL, and you can invalidate individual keys or entire groups on demand.
When should I not use this?
A cache is best-effort and can evict entries at any time, so it is not a primary datastore. Keep the source of truth in the database.