Caching PatternsLesson 3.3
Cache invalidation strategies: TTL, event-based, and tag-based invalidation
TTL-based invalidation, explicit delete on write, tag-based invalidation, cache key namespacing, versioned cache keys, invalidation fan-out problem
The hardest problem in caching
Phil Karlton famously said there are only two hard things in computer science: cache invalidation and naming things. Here are the three workable strategies.
TTL-based
Set a short TTL and accept brief staleness. Simplest approach โ no additional code on writes.
SET product:42 "{...}" EX 60 # stale for at most 60sEvent-based (explicit invalidation)
Delete or update the cache key whenever the underlying data changes.
async function updateProduct(id, data) {
await db.update(id, data);
await client.del(`product:${id}`); // force cache miss
}Tag-based invalidation
Group related cache keys under a tag. When data changes, delete all keys in that group.
// Store keys belonging to user:42's data
await client.sAdd('tag:user:42', 'user:42:profile', 'user:42:orders');
// On user update, invalidate all related keys
const keys = await client.sMembers('tag:user:42');
await client.del(keys);
await client.del('tag:user:42');Tag-based invalidation adds complexity but is powerful when one data change affects many cache keys. Use event-based for simple cases and tag-based for objects with many derived cache entries.
