Why cache at all?
A cache trades staleness for speed. You accept that data might be a little out of date in exchange for serving it far faster and taking load off the source of truth.
The most common pattern is cache-aside (lazy loading): the application checks the cache first, and on a miss, reads the database and populates the cache.
The two hard problems
- Invalidation — when the underlying data changes, stale cache entries must be removed or updated. Options: write-through (update cache on write), TTL expiry, or explicit invalidation on mutation. Each has tradeoffs between consistency and complexity.
- Stampede — when a hot key expires, thousands of requests miss simultaneously and hammer the database. Mitigations: request coalescing (single-flight), staggered TTLs, or serving stale-while-revalidate.
Key idea
The cache is never the source of truth. If your design treats it as authoritative, a cache eviction becomes data loss — that's a state-ownership bug, not a caching one.