Concept · Caching

Cache Strategies

01

Why this matters

A database lookup costs 1–10ms. A cache lookup costs 0.1–1ms. Your feed page makes 40 lookups. Without a cache you're over 100ms just on DB; with one you're under 5ms. That's the difference between a snappy app and a slow one.

But "put a cache in front of the DB" hides a design choice with five different answers, each wrong for some workload. The right cache strategy for a product catalog is the wrong one for a payment ledger.

02

Intuition

Think of a barista's memory. A customer orders a latte. Does the barista (a) always look up the recipe in the manual and write results on a sticky note after (cache-aside), (b) write to the manual AND their sticky note at the same time (write-through), (c) only update the sticky note and sync to the manual later (write-back), or (d) skip the sticky note entirely for writes (write-around)?

Each choice trades consistency for latency in a different direction. None is universally best.

03

The five strategies

StrategyRead pathWrite pathBest for
Cache-asideCheck cache → miss → read DB → fill cache → returnWrite DB, delete or update cacheMost app caches — read-heavy, tolerates brief staleness
Write-throughCheck cache → miss → read DB → fill cacheWrite cache AND DB synchronously. Both succeed or fail.When reads immediately after writes must be fresh
Write-backSame as write-throughWrite cache, acknowledge. Async flush to DB later.Write-heavy, tolerates data loss on crash (counters, analytics)
Write-aroundSame as cache-asideWrite DB only. Cache filled on next read.Write-once-read-rarely data (logs, audit trail)
Refresh-aheadCache hit returns stale if expiring soon; background refresh triggered.Writes go to DB as normalPredictable hot keys you want to pre-warm (feed caches, homepage)
04

Tradeoffs

Cache-aside (default)

Simple, survives cache outages

Cache can crash and reads still work (they just hit the DB). Writes don't block on cache. Problem: a read and a write racing can leave stale data in the cache. Mitigate with DELETE-on-write rather than UPDATE-on-write.

Write-through

Strong read-after-write consistency

Every successful write is readable from cache immediately. Problem: every write is now two operations. Cache outage blocks writes. Use only when you genuinely need read-after-write consistency (user profile updates, settings).

Cache invalidation

"There are only two hard things in computer science: cache invalidation and naming things." — Phil Karlton. The harder the consistency you promise, the more expensive invalidation becomes. Prefer short TTLs with cache-aside over "perfect" invalidation logic.

05

Deep dive — the stale-read race in cache-aside

Consider two clients hitting the same key:

  1. Client A: read cache → miss
  2. Client A: read DB (gets value v1)
  3. Client B: write DB (new value v2)
  4. Client B: delete cache key
  5. Client A: write cache key ← writes the now-stale v1

Cache now holds v1; DB holds v2. Cache is stale forever (until TTL). This race exists in any cache-aside system. Mitigations:

  • Short TTLs — stale window bounded (e.g., 60s).
  • Double-delete — B deletes the cache, sleeps 500ms, deletes again. Catches A's late write.
  • Versioned values — cache entry stores {value, version}. On write, A's version is older, gets rejected.
  • Write-through instead — eliminates the race entirely but costs latency on every write.

The interview answer: "cache-aside is correct for most workloads if you pair it with short TTLs. If you need read-after-write, switch that specific key's strategy to write-through — don't redesign the whole cache."

06

Real-world

Facebook TAO

Cache-aside at planet scale

Billions of entries, 99% read hit rate. Uses leases to mitigate the stale-read race — a reader holds a lease while filling, subsequent writers wait.

Redis in front of Postgres

Classic cache-aside

The textbook setup. App checks Redis, falls back to Postgres, stores result. Delete on write. TTL of 60s–24h depending on volatility.

DynamoDB DAX

Write-through

AWS's managed cache in front of DynamoDB. Writes go through DAX, which writes to DynamoDB synchronously. Zero stale reads.

CDN

Write-around + long TTL

CDNs rarely see writes — they pull from origin on first request (write-around is implicit). Invalidation is explicit (POST /purge).

07

Used in problems

URL shortener caches redirects (cache-aside, TTL 24h). News feed caches rendered feeds (cache-aside + refresh-ahead). Ticketmaster caches event availability (write-through to keep inventory accurate).

Next up