The Question Reframed
cache consistency ≠ database consistency.
it asks: how stale may a COPY be, and who notices?
levels in practice:
1. UNBOUNDED no TTL, no invalidation ← never do this
2. BOUNDED TTL caps staleness ← most systems live here
3. READ-YOUR-WRITES user sees own edits immediately
4. MONOTONIC once you've seen v2, never see v1 again
5. STRICT every read sees latest write ← expensive; rare
pick PER DATA CLASS. strictness everywhere is unaffordable;
sloppiness everywhere is a support nightmare.
The Classic Anomalies
STALE READ:
writer updates db → reader's copy still old until TTL/invalidation
READ-YOUR-WRITES violation (the one users notice):
user renames profile → page reload → OLD name (their read hit
a replica/cache that missed their write)
MONOTONIC violation (rare but maddening):
refresh shows new data, next click shows older — reads bouncing
across differently-stale copies
Achieving Read-Your-Writes Pragmatically
techniques, cheap to expensive:
1. VERSION STAMPING:
on write, record ver in session/token
reads: if cached.ver < session.ver → bypass/refetch
2. WRITE-ROUTE AFFINITY:
route THIS USER's reads to primary (or same replica) for N sec
after their write ("sticky-after-write" window)
3. SHORT-TTL + IMMEDIATE INVALIDATION COMBO:
invalidate event usually wins the race;
TTL catches events that got lost
technique 1 is precise and cheap — default recommendation.
Multi-Copy Drift Control
with L1(local)+L2(redis)+CDN layers:
[pod L1: ttl 2s] ──► [redis: ttl 120s] ──► [cdn: ttl 300s]
worst-case staleness SUMS across layers (~7 min!).
control it:
- keep L1 TTLs TINY (seconds) — they're herd shields, not truth
- invalidation messages target ALL layers (bus fans out)
- version keys so stale layers self-retire on next fill
document the worst case per layer stack — surprises here
become "sometimes users see old avatars" tickets forever.
What Caches Should NEVER Promise
✗ linearizability across the fleet (use the db for that)
✗ cross-key transactional consistency
✗ durable storage of anything (it's a cache!)
locks on redis: fine WITH fencing tokens and timeouts,
because redis is not a consensus system by default —
treat coordination data as advisory unless using
Redlock-with-fencing or a real consensus store.
Consistency Budget Table
| Data | Target level | Mechanism |
|---|---|---|
| Product info | Bounded (60s TTL) | TTL only |
| User’s own profile edits | Read-your-writes | Version stamping |
| Cart contents | Strong-ish | DB-backed, short cache |
| Session auth | Bounded 30s + revoke path | TTL + denylist |
| Public pages CDN | Bounded minutes | Surrogate TTL + purge |
Interview Framing
Consistency questions on caches are really scoping questions. Scored shape: declare per-data-class targets (table-style), implement read-your-writes with version stamping for the personalization cases, bound everything else with TTL+invalidation, state what the cache never promises. The phrase “consistency budget per data class” itself signals senior design maturity.
Premium Content
Unlock Cache Consistency and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans