Redis answers reads in well under a millisecond, which makes it the default choice for caching in front of a relational database. But caching is easy to get subtly wrong. This guide covers the patterns you'll actually use and the pitfalls to avoid.
Cache-aside (lazy loading)
The application owns the logic: check the cache first, fall back to the database on a miss, then populate the cache.
async function getProduct(id: string) {
const key = `product:${id}`;
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const product = await db.product.findUnique({ where: { id } });
if (product) {
await redis.set(key, JSON.stringify(product), { EX: 300 }); // 5-minute TTL
}
return product;
}
Pros: only data that's actually requested gets cached; a Redis outage degrades to "slower", not "down". Cons: the first request after expiry is slow; data can be stale until the TTL expires.
Invalidate on write
When data changes, delete the cache entry rather than trying to update it:
() {
db..({ : { id }, data });
redis.();
}
