Caching Strategy
Decide what to cache, where, and how to invalidate — the three questions that determine if cache helps or hurts.
Why
A cache that's never hit wastes memory; a cache that's stale serves wrong data; a cache that's invalidated too aggressively is just a slow network call. Caching strategy is the art of placing data at the right layer (browser, CDN, app, DB) with the right TTL and the right invalidation trigger. Done well, it cuts DB load 80% and latency 10x; done poorly, it creates a stale-data bug that's nearly impossible to reproduce because it depends on timing. The strategy must be explicit per data type — a single global TTL is a sign no one thought about it.
When
When a read path is slow or a DB is overloaded. Takes half a day to design. Revisit when hit rates drop or staleness bugs appear.
How
1. For each data type, classify: static (rarely changes), near-static (changes minutely), dynamic (changes constantly) 2. Static (config, product catalog) → CDN + long TTL (1h-1d), invalidate on write 3. Near-static (user profile) → app cache (Redis) + TTL (1-5min) + write-through 4. Dynamic (real-time inventory) → no cache, or very short TTL (5s) with stale-while-revalidate 5. Choose invalidation: TTL (simple, eventually-consistent) vs explicit (complex, always-fresh) - Default to TTL; use explicit only when stale data causes harm (e.g. prices) 6. Measure hit rate per cache; < 80% means the working set doesn't fit or TTL is too short 7. Add a cache stampede guard (single-flight or jittered TTL) for hot keys
Example
Data types and strategy: product_catalog → CDN, TTL 1h, purge on admin write (static) user_profile → Redis, TTL 5min, write-through (near-static) order_status → no cache (must be real-time) (dynamic) price → Redis, TTL 30s, explicit purge on change (stale = lost money) Hit rates after 1 week: product_catalog: 97% (CDN) ✓ user_profile: 84% (Redis) ✓ price: 91% (Redis) ✓ — stampede guard on the top 10 SKUs
Common Problems
- ⚠Caching everything with one TTL — dynamic data goes stale, static data is under-cached; tune per data type.
Best Practices
- ✓Measure hit rate and latency separately per cache layer — a 95% hit rate that adds 50ms on miss is worse than no cache for tail latency.
- ✓Always have a fallback when the cache is down — the system must still serve correct data, just slower; never make the cache a hard dependency.