Caching is the most reliable way to make software faster, because the quickest work is the work you skip. But it comes with one of computing’s famous hard problems — knowing when cached data has gone stale. Good caching is as much about invalidation as about storage.
Why cache at all
Some results are expensive to produce — a complex query, a slow API call, a heavy computation — but are needed repeatedly and change rarely. Caching stores the result so subsequent requests get it instantly, sparing the expensive work. The payoff is speed and reduced load; the price is the risk of serving data that has since changed.
The common patterns
- Cache-aside — the application checks the cache first, and on a miss fetches from the source and stores it. The most common and flexible pattern.
- Write-through — writes go to the cache and the source together, keeping them in sync at the cost of slower writes.
- Write-behind — writes hit the cache and are flushed to the source later, fast but riskier if the cache fails.
The hard part: invalidation
There is a famous saying that the two hard things in computing are naming things and cache invalidation. The challenge is knowing when cached data no longer matches reality. The simplest tool is a time-to-live (TTL) — data expires after a set period, accepting brief staleness in exchange for simplicity. More precise is explicit invalidation: actively removing or updating a cache entry the moment the underlying data changes, which is exact but easy to get wrong.
Practical guidance
Cache things that are read far more than they change, and be honest about how stale they may safely be. Start with a sensible TTL — it is simple and robust — and add explicit invalidation only where staleness genuinely matters. Always have a correct path when the cache is empty or unavailable, so the cache is an optimization, never a dependency you cannot live without.
- Cache results that are read often and change rarely.
- Cache-aside is the common default; write-through keeps cache and source in sync.
- Invalidation is the hard part — TTLs are simple, explicit invalidation is precise.
- Guard against cache stampedes and never let the cache become a hard dependency.
Frequently asked questions
What is a good TTL?
It depends entirely on how stale the data may safely be. Seconds for fast-changing data, hours or days for stable data. There is no universal answer — match it to the data.
Cache-aside or write-through?
Cache-aside is simpler and more common, giving the app full control. Write-through keeps the cache fresh automatically at the cost of slower writes. Choose based on read/write balance.