A cache is a promise about time
Fast is only useful when the data is still appropriate. Think freshness, ownership, and invalidation before hit rates.
A cached answer says more than “we have seen this before.” It says “this earlier result is still suitable for this request.” That second claim is where most of the design work lives. Before choosing a cache duration, decide what becoming stale would mean for the person using the result.
Different data has different consequences
An old portfolio thumbnail and an old permission decision are not equivalent mistakes. The thumbnail might be visually outdated. A reused permission decision could expose information to someone whose access has changed. Treating both as a generic performance problem hides the actual risk.
For a hypothetical article site, versioned image assets can tolerate long-lived caching because a changed image receives a new URL. An article's title may need faster revalidation. A private account page needs its own rules about who can store and reuse the response. Begin by identifying ownership and freshness requirements, then choose the mechanism.
Understand what the header promises
HTTP caching has vocabulary that is easy to misread. As MDN explains, no-cache permits storage but requires validation before reuse; no-store asks caches not to store the response. They are not interchangeable. Private limits storage to private caches, while public can permit shared caching under the relevant rules.
An ETag gives a server a validator for checking whether a stored representation is still current. That can avoid transferring a full response when it has not changed. It does not automatically solve application-level permission checks or choose the right cache key for personalised content.
Make identity part of the design
Suppose a dashboard endpoint returns a summary for the signed-in organisation. If an application cache uses only the endpoint path as its key, one organisation's response may be reused for another. Include the dimensions that actually change the result, or avoid caching that response where safe isolation is unclear.
The same issue appears with language, feature flags, and document versions. Every added key dimension can reduce reuse, but omitting a necessary one changes correctness. A low hit rate is preferable to a high hit rate for the wrong answer.
Plan how old answers leave
Expiration is one approach; explicit invalidation is another. For an article edit, invalidating the specific cached article might give a better experience than waiting for a long timeout. For a rarely changing public catalogue, a bounded stale period might be acceptable. Neither choice is universally correct.
Measure user-facing latency and freshness failures together. A faster response is not a successful optimisation if it routinely contradicts a change the user just saved. Good caching is a deliberately limited memory: it remembers the right things, for the right audience, for a reason you can explain.
Further reading: MDN: HTTP caching.