Caching: What to Cache, Where, and When to Stop
Caching trades freshness for speed. Done well it makes a slow thing fast for almost no cost. Done carelessly it serves last week's price, shows one user another user's data, and produces bugs that...

Caching trades freshness for speed. Done well it makes a slow thing fast for almost no cost. Done carelessly it serves last week’s price, shows one user another user’s data, and produces bugs that only appear for some people some of the time. The trick is to cache the things where the trade is clearly worth it and leave the rest alone.
Cache what is shared and slow-changing
The safe, high-value targets are the same for every user and change rarely: images, scripts and styles, public pages, country lists, product catalogues that update daily. Put a long lifetime on these and version the URL, so app.a1b2c3.js replaces app.d4e5f6.js and the browser fetches the new one because it is a new address. You never have to invalidate anything.
Be careful with anything per-user
Never put user-specific responses in a shared cache. A cache keyed only by URL will happily hand one person’s account page to the next person who asks for that URL. If you must cache per-user data, key it by the user as well, keep it local to that user’s session, and keep the lifetime short.
Choose the layer deliberately
The browser cache is free and closest to the user, good for assets. A content delivery network caches at the edge, good for public content and static files. An in-memory cache in the application, or a shared store like Redis, is for computed results and database query output. Each layer you add is another place a stale value can hide, so add the one that solves your actual bottleneck and not the others.
Have an invalidation plan before you start
Every cache entry needs an answer to “how does this get refreshed”. Options, roughly in order of preference: a short time to live so it simply expires; an explicit purge triggered by the code that changes the underlying data; or a versioned key so a change produces a new address. If your only plan is “it expires in an hour and users will cope”, be honest that you have chosen to show stale data for up to an hour.
Measure the win
Add the cache, then check it actually helped: response times, database load, hit rate. A cache with a ten percent hit rate is adding complexity for almost no benefit and should be removed. Caching is not automatically good; it is good when the numbers say so.
Know when to stop
If the thing is already fast enough for the user, do not cache it. If keeping the cache correct would cost more than the speed is worth, do not cache it. The best caching decision is often not to add one.
Common questions
What is safe to cache aggressively?
Anything that is the same for everyone and rarely changes: static assets, public content, reference data. Version the URL so a change gets a fresh copy.
How do we avoid serving stale data?
Short lifetimes for data that changes, explicit invalidation when you can hook into the change, and never cache anything user-specific in a shared layer.
When should we not add a cache?
When the thing is already fast enough, or when correctness matters more than speed and you cannot cheaply keep the cache correct. A wrong answer served quickly is still wrong.


