Distributed Caching Strategy — Patterns and Trade-offs
Fast recall
Quick revision
Core answer
Multi-layer cache topology, read/write pattern selection, eviction & TTL, and operational hazards (stampede, hot key, staleness, consistency).
Treating Redis as a single 'the cache' with one TTL, ignoring stampedes, and using write-back for systems where data loss is unacceptable.
Justify per-key cache pattern based on read/write ratio + tolerance for staleness, walk through stampede mitigation (singleflight + jitter), and discuss invalidation via pub/sub for multi-instance L1 caches.
Interview-ready guide
Interview answer
Clarifying questions I'd ask first
- What's the read/write ratio per data type?
- How stale can the cached data be — seconds, minutes, hours?
- Multi-instance fleet — do they need to agree on cached values?
- Critical paths that can never read stale (payments, inventory)?
- Hot key suspects (top product, viral content)?
Layered caching topology
- L1 in-process (Caffeine): ~100ns, hottest keys, eventual consistency across instances
- L2 distributed (Redis cluster): ~1ms, shared state, sharded by key hash
- L3 CDN/edge: ~10-50ms, public HTTP responses with short TTLs
Read/write patterns — pick per use case
- Cache-aside is the safe 95% default — app reads cache, on miss reads DB, populates cache; on write, updates DB then invalidates cache
- Read-through wraps the miss in the cache library (Caffeine LoadingCache)
- Write-through writes to cache and DB synchronously — strong consistency at write-latency cost
- Write-behind batches DB writes asynchronously — fast but risks data loss; reserve for metrics/counters
Eviction
- LRU default; LFU (W-TinyLFU in Caffeine) for stable hot sets
- TTL is the freshness contract; LRU is the size contract — use both
- Jitter TTLs (base ± random) to avoid synchronized expiry stampedes
Stampede mitigation — multiple defenses together
- Singleflight: first miss locks the key, others wait and reuse the result
- Jittered TTL spreads expiries
- Probabilistic early refresh smooths the cliff
- Stale-while-revalidate returns stale immediately, refreshes in background
- Negative caching for missing-key probes
Hot keys
- Local L1 absorbs heat for super-hot keys
- Shadow-key replication (
product:42:0,:1, ...) spreads across shards - Read replicas for read-heavy hot keys
- Pre-aggregate counters in app then flush
Multi-instance L1 coherence
- Versioned keys eliminate read-after-write races
- Pub/sub invalidation bus broadcasts evicts to all app instances; bounded staleness in milliseconds
LLD
- One
LayeredCacheManagerfaçade hides tiers from app code CacheLayerinterface (Caffeine impl, Redis impl, in-memory test impl)StampedeGuard.singleflight(key, loader)for the miss pathTtlPolicycentralizes per-key TTLInvalidationBuskeeps L1s coherent
Failure modes
- Cache outage = DB overload (hit rate collapse → 100x DB traffic) — needs circuit breaker + L1 fallback
- Split-brain on concurrent writes — versioned keys with monotonic version check
- Stale-after-deploy — schema version in cache key
- Memory pressure — alert on evicted_keys/sec before thrashing
Recommendation
Three-tier topology (L1 Caffeine + L2 Redis + L3 CDN), cache-aside as the default pattern with read-through where the abstraction fits, LRU+TTL with jitter, singleflight for stampedes, local L1 for hot keys, versioned keys with pub/sub invalidation for multi-instance coherence, and a circuit breaker on the source DB so cache outage doesn't cascade. That's the same shape Netflix, Stripe, and modern Spring/Java stacks run.
Distributed Caching Strategy — Patterns and Trade-offs
Direct Answer
Layer caches by latency budget: L1 in-process (Caffeine, ~100 ns) for hottest keys, L2 distributed (Redis cluster, ~1 ms) for shared state, L3 CDN/edge for cacheable HTTP. Pick a read/write pattern per use case — cache-aside is the safe default; read-through and write-behind have specific niches. Set TTLs and eviction (LRU/LFU) per workload. Defend against stampedes (request coalescing + jittered TTL), hot keys (key replication or local L1), and stale data (versioned keys + invalidation events).
Common Mistakes & Pitfalls
Treating Redis as a single 'the cache' with one TTL, ignoring stampedes, and using write-back for systems where data loss is unacceptable.
Check your understanding
Answer these without looking back at the article.
- Walk through the exact sequence when a hot key (1M req/s) expires — what fails without singleflight?
- How would you migrate a cache from one schema to another with zero downtime?
- When does write-through become preferable to cache-aside?
- Design a per-region cache topology where regions need to share invalidations but data is regional.
Related interview prep categories
2Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.