A cache can miss on every request or never store a response at all, even with a sensible Cache-Control header. Start with the cache key, verify real responses and plan invalidation.

A public endpoint can have a technically correct cache header and still provide no protection against repeat traffic. Two questions decide whether caching helps: what request variations map to the same cache key, and does the deployed path actually cache the response?
Answer both with live requests before calling an optimisation finished. A header expresses cache policy. It does not prove that every CDN, gateway or framework layer in front of the endpoint will store and reuse the response.
A cache stores a response under a key. A CDN can include the URL path, query string, headers, cookies and other dimensions in that key. Cloudflare’s cache-key documentation describes those components and the options for customising them.
Suppose a public price endpoint ignores query parameters. To the application, `/prices?x=1` and `/prices?x=2` are identical. If the CDN treats them as separate keys, both requests miss the stored response and reach the origin. A script that changes an irrelevant parameter can turn a cache into a pass-through.
Pick the narrowest approach that matches the endpoint contract. Never ignore a parameter that changes price, locale, experiment, authorisation or any response content. Cache correctness is a privacy and data-integrity decision, not just a performance detail.
A header such as `Cache-Control: public, max-age=60, s-maxage=300` gives different instructions to a browser and a shared cache. MDN’s Cache-Control reference explains directives including `public`, `no-store`, `max-age` and `s-maxage`. A private or error response may need stricter directives than a successful public response.
Set these directives intentionally, but do not mistake them for an observation. A platform may bypass caching for dynamic routes, cookies, headers or its own product rules. Test a sequence of real requests and inspect the cache-status and Age headers supplied by the infrastructure you actually use.
Public data such as catalogue information or published prices needs a freshness plan. An explicit invalidation lets the product clear the affected value when an operator changes it. A modest time-to-live then limits the impact if that invalidation is missed.
In Next.js, a cache tag can group related data so a route handler or server function can revalidate the tag on a deliberate change. The exact mechanism varies by platform, but the design principle remains: name the cached thing, clear it at the source of change and retain a bounded fallback lifetime.
Client-side data caches also use keys. A key that is too specific creates duplicated copies of identical public data. A key that is too broad can display one tenant’s data while another tenant is active. Include the values that genuinely change the answer, keep their positions consistent and clear the relevant keys when that context changes.
The cache key is part of the data model. Treat it with the same care you give an API parameter or database constraint.
Caching is valuable because it changes the real work a system performs under repeat demand. That benefit is earned by a correct key, a response safe to share and evidence from the deployed route. Start there, and a performance header becomes an operational control rather than decoration.
Ready when you are