Skip to main content
  1. References/
  2. Architecture Design Basics/
  3. Pattern Taxonomy/
  4. Scaling & Performance/

Cache Invalidation

·· 260 words· 2 mins

🔴 P0 — “There are only two hard things in CS: cache invalidation and naming things”

Problem #

Cached data becomes stale when the source changes. Serving stale data is sometimes acceptable (product listings), sometimes not (account balance). The question is: when and how to invalidate.

Strategies #

StrategyMechanismStalenessComplexity
TTL-basedCache entry expires after N secondsUp to TTL secondsLowest
Event-basedDB write triggers cache invalidationNear-zeroMedium
Write-throughCache updated on every writeZeroHigher
Versioned keysCache key includes version/timestampZero (reads miss)Low

The Race Condition Problem #

Thread 1: UPDATE DB (balance = 100)
Thread 2: UPDATE DB (balance = 200)
Thread 2: SET cache (balance = 200)
Thread 1: SET cache (balance = 100)  ← WRONG! Stale value overwrites fresh

Solution: INVALIDATE cache on write (delete key), don't update it.
Next read will fetch fresh value from DB.

Instinct #

TTL + event-based invalidation is the sweet spot for most systems. TTL as a safety net (maximum staleness bound), event-based invalidation for important mutations (payment completed → invalidate balance cache). Never update the cache on write — always invalidate. The next reader will populate from the source of truth.

  • EXP: In practice, cache invalidation on writes (delete-on-write) combined with short TTLs as a safety net has been the most operationally robust approach I’ve seen. Pure TTL-based is simpler but the staleness window is harder to reason about under load.

Thundering Herd Mitigation #

When a popular cache key expires, hundreds of requests simultaneously hit the database. Aka cache-stampedes.

Solutions:

  • Stale-while-revalidate: serve stale value while one request refreshes
  • Lock-based refresh: only one request fetches from DB, others wait
  • Early Recomputation: refresh entries before they expire
  • Staggering TTLs / Jittered TTLs: add randomness to TTL to avoid simultaneous expiration

References #