Caching Strategies
Caching stores the result of expensive work so you don't repeat it — dramatically cutting latency, database load, and compute cost. A well-placed cache can turn a 200 ms query into a sub-millisecond lookup.
The hard part isn't storing data; it's invalidation — knowing when a cached value is stale. Get the layering and invalidation right and caching is nearly free wins; get it wrong and you serve users incorrect data.
TL;DR
- Cache at multiple layers: CDN → application → database → client.
- Default to cache-aside with a TTL for most read-heavy data.
- Have a clear invalidation strategy (TTL, event-based, or versioned keys).
- Protect against stampedes when popular keys expire.
- Monitor hit rate and memory — a cache nobody hits is just risk.
Quick Example
The cache-aside pattern — check the cache, fall back to the database, then populate with a TTL:
Core Concepts
Cache layers
- CDN — static assets and cacheable API responses at the edge.
- Application — in-memory stores (Redis, Memcached).
- Database — query cache and buffer pool.
- Client — browser cache and service workers.
Read/write strategies
Invalidation
- TTL — expire after a time window (simplest, slightly stale).
- Event-based — invalidate on the write that changed the data (fresh, more wiring).
- Versioned keys — bake a version into the key so old entries age out naturally.
Best Practices
Design cache keys deliberately
Include every input that affects the result, normalize ordering, prefix by domain (user:123), and decide explicitly whether a key is shared or per-user.
Protect against stampedes
When a hot key expires, many requests can hit the database at once (the "thundering herd"). Mitigate with a short lock around recomputation, "stale-while-revalidate," or jittered TTLs.
Use HTTP caching for cacheable responses
Common Mistakes
Caching personalized data in a shared cache
No invalidation plan
FAQ
What should I cache first?
Expensive, read-heavy, rarely-changing data: reference lookups, rendered pages, aggregations, and slow query results. Don't cache cheap, fast, or highly volatile data — the overhead outweighs the benefit.
How long should a TTL be?
As long as you can tolerate the data being stale. Seconds for fast-changing data, minutes to hours for stable data. When in doubt, start short and lengthen it while watching the hit rate.
How do I avoid serving stale data?
Pair a TTL with event-based invalidation: expire on a schedule and proactively bust the key on the write that changes it. For critical correctness (permissions, balances), prefer write-through or explicit invalidation over TTL alone.
What is a cache stampede?
When a popular key expires and many concurrent requests all miss and recompute it at once, overloading the backend. Locking, request coalescing, stale-while-revalidate, and jittered TTLs prevent it.
Related Topics
- Redis — The most common application cache
- Web Performance — Browser and CDN caching
- REST API Design —
ETagandCache-Control - Rate Limiting — Shedding load caching can't absorb
- Database Indexing — Speeding up the misses