Skip to main content
Version: Next

Caching

Accessing the database can be expensive for complex queries or if you need to run many different queries for a specific task. Serverpod makes it easy to cache frequently requested objects in the memory of your server. Any serializable object can be cached. Objects can be stored in the Redis cache if your Serverpod is hosted across multiple servers in a cluster.

Caches can be accessed through the Session object. This is an example of an endpoint method for requesting data about a user:

Future<UserData> getUserData(Session session, int userId) async {
// Define a unique key for the UserData object
var cacheKey = 'UserData-$userId';

// Try to retrieve the object from the cache
var userData = await session.caches.local.get<UserData>(cacheKey);

// If the object wasn't found in the cache, load it from the database and
// save it in the cache. Make it valid for 5 minutes.
if (userData == null) {
userData = UserData.db.findById(session, userId);
await session.caches.local.put(cacheKey, userData!, lifetime: Duration(minutes: 5));
}

// Return the user data to the client
return userData;
}

In total, there are three caches where you can store your objects. Two caches are local to the server handling the current session, and one is distributed across the server cluster through Redis. There are two variants for the local cache, one regular cache, and a priority cache. Place objects that are frequently accessed in the priority cache.

Depending on the type and number of objects that are cached in the global cache, you may want to specify custom caching rules in Redis. This is currently not handled automatically by Serverpod.

Cache miss handler

If you want to handle cache misses in a specific way, you can pass in a CacheMissHandler to the get method. The CacheMissHandler makes it possible to store an object in the cache when a cache miss occurs.

The above example rewritten using the CacheMissHandler:

Future<UserData> getUserData(Session session, int userId) async {
// Define a unique key for the UserData object
var cacheKey = 'UserData-$userId';

// Try to retrieve the object from the cache
var userData = await session.caches.local.get(
cacheKey,
// If the object wasn't found in the cache, load it from the database and
// save it in the cache. Make it valid for 5 minutes.
CacheMissHandler(
() async => UserData.db.findById(session, userId),
lifetime: Duration(minutes: 5),
),
);

// Return the user data to the client
return userData;
}

If the CacheMissHandler returns null, no object will be stored in the cache.