Purpose: store frequently-read data closer to the reader and faster than the source, so you serve hot reads without hammering the database. The universal trade-off: speed for freshness.
Where caches live (the layers)
Client — browser/device cache, local storage (zero network cost)
CDN — edge cache for static assets and public content, geographically close
Load balancer / reverse proxy — response caching
Application — in-memory cache (Redis, Memcached) for hot data
Database — its own buffer pool (you get this for free)
The rule: cache at the layer closest to the user that still gives correct-enough data.
The three patterns
Pattern
How
Read
Write
Use when
Cache-aside
App checks cache → miss → loads DB → writes cache
Lazy
App invalidates/updates cache
Most systems
Write-through
Every write also writes cache
Always fresh
Slower writes
Read-heavy, must be fresh
Write-back
Write goes to cache, flushed to DB later
Fast
Risk of loss if cache dies
Tolerates loss, write-heavy
TTL (time-to-live) is the safety valve: every cache entry expires, bounding how stale data can get even if invalidation fails.
The failure modes a senior designs for
Cache stampede (thundering herd): cache entry expires, 10,000 requests all miss and all hit the DB at once. Fix: singleflight (one request loads, others wait) or stale-while-revalidate.
Hot key: one key (a viral user, a popular product) is read so often it saturates a single cache shard. Same skew as partition hot keys.
Staleness: cache says one thing, DB another. Your call: how fresh must this data be? That decides the pattern and TTL.
Cache death ≠ data loss (usually). A cache is a cache — if it's wiped, you should be able to rebuild it from the source. If you can't, you've accidentally built a database.
Where it fits your systems
Your device-token lookup was the exact case: Redis cache on user_id → tokens, because reading tokens per notification (12k QPS) would hammer MongoDB. The two sharpening rules from that session apply everywhere: invalidate on change, and the cache is a cache — the DB is the truth.
Ask yourself
What's my read:write ratio? (High ratio → cache wins.)
How stale can this data be? (Determines TTL and pattern.)
If the cache vanishes at 9 AM, does my system still work?