Cache Strategies
Caching stores copies of expensive computation or data closer to consumers — in-process, Redis, or CDN.
Introduction
Caching stores copies of expensive computation or data closer to consumers — in-process, Redis, or CDN. Cache strategies define who reads/writes the cache and when: cache-aside, read-through, write-through, write-back, and refresh-ahead. Wrong strategy causes stale data, lost writes, or thundering herds.
HLD interviews expect you to pick a strategy per data type, explain invalidation, and handle cache failure (fail open vs closed). Product catalog tolerates staleness; inventory and pricing need tighter consistency.
This lesson maps strategies to use cases and failure modes.
Understanding the topic
Key concepts
- Cache-aside (lazy): app manages cache; most flexible, common in microservices.
- Read-through: cache library loads on miss — simpler app code.
- Write-through: write cache and DB synchronously — consistent but slower writes.
- Write-back (write-behind): write cache first, async flush to DB — fast, data loss risk.
- Invalidation: TTL, event-driven purge, versioned keys (product:v42:id).
- Cache stampede: many misses on expiry — mitigate with jitter, single-flight lock.
flowchart LRApp -->|1 read| CacheCache -->|2 miss| DBDB -->|3 populate| Cache
Internal architecture
Architecture overview
flowchart LRApp -->|1 read| CacheCache -->|2 miss| DBDB -->|3 populate| Cache
Step-by-step explanation
- Hot read path: CDN → Redis → DB for three-tier caching.
- On product update: publish ProductUpdated event → consumers DEL cache keys.
- Negative caching: cache 'not found' briefly to protect DB from scrapers.
- Local in-process Caffeine cache L1 + Redis L2 for ultra-hot keys.
- Circuit breaker on Redis failure: fall through to DB with rate limit.
- Warm cache on deploy via background loader for top 10k SKUs.
Informative example
Write-through vs cache-aside — Spring cache eviction on update with single-flight miss protection:
@Servicepublic class PricingService {private final StringRedisTemplate redis;private final PriceRepository db;public PricingService(StringRedisTemplate redis, PriceRepository db) {this.redis = redis;this.db = db;}public BigDecimal getPrice(String sku) {String key = "price:" + sku;String val = redis.opsForValue().get(key);if (val != null) return new BigDecimal(val);synchronized (("lock:" + sku).intern()) {val = redis.opsForValue().get(key);if (val != null) return new BigDecimal(val);BigDecimal price = db.findPrice(sku);redis.opsForValue().set(key, price.toPlainString(), Duration.ofMinutes(5));return price;}}@Transactionalpublic void updatePrice(String sku, BigDecimal price) {db.save(sku, price);redis.delete("price:" + sku); // invalidate, not write-through unless required}}
Single-flight reduces stampede. Financial pricing may need write-through or shorter TTL + event invalidation.
Real-world use
Real-world use cases
- E-commerce: CDN for images, Redis for prices, Caffeine for config flags.
- Banking FX rates: read-through with 60s TTL and admin purge.
- OTT: manifest cache short TTL; segment cache long TTL at CDN.
- Social graph: write-back too risky — cache-aside follower lists with event invalidation.
Best practices
- Classify data: immutable (long TTL), soft stale OK (minutes), must-fresh (no cache or seconds).
- Use TTL jitter on popular keys.
- Monitor hit rate, miss latency, eviction rate.
- Version keys on schema change — avoid deserialization errors.
- Document cache failure behavior in runbooks.
- Load test with cold cache scenario.
Common mistakes
- Caching without invalidation on write — stale prices forever until TTL.
- Write-back without durability plan — data loss on crash.
- Caching personalized responses keyed wrong — privacy leak.
- Infinite TTL on mutable data.
- Ignoring thundering herd on hot key expiry during sales.
Advanced interview questions
Q1BeginnerWhat is cache-aside?
Q2BeginnerWrite-through vs write-back?
Q3IntermediateHow prevent cache stampede?
Q4IntermediateCache fail open or closed?
Q5AdvancedCache strategy for flash sale inventory?
Summary
Pick cache strategy per data consistency needs. Cache-aside is default; write-through for strong sync requirements. Invalidation via TTL, events, or versioned keys. Stampede protection is mandatory on hot keys. Multi-tier: CDN, Redis, local cache. Message queues decouple cache warming and async invalidation.