System design · Day 6
Caching: make repeated work cheap
Place caches deliberately, choose an update strategy, and reason about freshness, eviction, stampedes, and invalidation.
A cache stores the result of expensive work closer to where it will be requested again. It trades some freshness and complexity for lower latency and reduced load.
Cache where repetition occurs
Browsers cache static assets, CDNs cache content near users, application caches hold computed or database results, and databases maintain internal page caches. Begin with the bottleneck found through measurement rather than adding Redis by reflex.
A strong cache candidate is expensive to produce, requested frequently, and tolerant of brief staleness. User permissions and bank balances demand different freshness rules than product images or public profiles.
Choose a read and write strategy
Cache-aside is a common start: read the cache, load from the database on a miss, then populate the cache. Writes update the database and invalidate the key. A time-to-live removes forgotten values but should not be the only correctness mechanism.
Write-through updates cache and database together; write-behind accepts the cache update and persists later. The latter improves write latency but risks data loss, so reserve it for cases whose durability model explicitly allows that trade.
Prepare for misses at scale
Eviction removes entries when memory fills. A cache stampede happens when a popular key expires and many requests recompute it together. Add expiry jitter, request coalescing, or refresh popular values before expiration.
Caching reduces repeated reads; it does not help slow work that must happen after every request. Day 7 introduces queues for moving that work off the user's critical path.
“A cache is a performance copy, not the source of truth, unless you deliberately design it to be one.”