Cache Invalidation

This is the hard one. "There are only two hard things in computer science: cache invalidation and naming things" names it directly — cache invalidation is genuinely, notoriously difficult. The moment you cache a copy of data, you've created a second source of truth that can drift from the first, and keeping them in sync (or deciding how much drift you'll tolerate) is a problem with no clean, universal solution. Understanding why it's hard, and the strategies for managing it, is the difference between caching that helps and caching that causes baffling bugs.

Cache invalidation — keeping cached data consistent with the source as the source changes — is the genuinely hard problem of caching. This post covers why it’s hard (the fundamental staleness problem), the main strategies (TTL/expiration, explicit invalidation, and write-through updates), the consistency tradeoffs, and practical guidance. It’s the topic that makes caching difficult, and handling it well (or choosing to tolerate staleness) is essential to caching correctly.

The staleness problem

The core difficulty: a cache holds a copy of data, and when the source data changes, the cached copy becomes stale (out of date) — and reconciling this is genuinely hard:

The staleness problem — a cached copy drifts from its changing source, and reconciling them is genuinely hard (detecting and propagating changes reliably) — is why cache invalidation is notoriously difficult. It reflects the fundamental consistency-vs-performance tradeoff of caching. The strategies for managing it don’t eliminate the tradeoff; they navigate it differently.

Strategy 1: TTL (expiration)

The simplest invalidation strategy is TTL / expiration (from the eviction post) — letting cached data expire after a set time rather than explicitly tracking changes:

TTL/expiration is the simplest invalidation strategy — accept bounded staleness (data at most TTL-old) by expiring items after a time, sidestepping the hard change-detection problem — widely used for staleness-tolerant data, with TTL length tuning the freshness/hit-rate tradeoff. When you need fresher-than-TTL consistency, you must actively invalidate.

Strategy 2: explicit invalidation and write updates

For fresher consistency, you actively keep the cache in sync when the source changes — explicit invalidation or write-through/write-update strategies:

Active strategies — explicit invalidation (remove the cache entry when the source changes, so it refetches) and write-through/write-update (update the cache on writes) — give fresher consistency than TTL but require reliably tracking and handling every source change, which is where the invalidation difficulty lies. They trade complexity for freshness. And even these don’t guarantee perfect consistency.

The consistency spectrum and practical guidance

Invalidation is really about choosing a point on a consistency spectrum — and practical caching means choosing deliberately:

Cache invalidation is caching’s genuinely hard problem — a cached copy drifts from its changing source, and reconciling them navigates the fundamental consistency-vs-performance tradeoff — managed via TTL (accept bounded staleness, simple, preferred when tolerable), explicit invalidation/write-through (fresher but hard — reliably track changes), choosing a point on the consistency spectrum by staleness tolerance, and designing for staleness. Next: caching patterns — how applications and caches interact.

Key takeaways

Further reading

Sources & References

The staleness problem