A query string can change a URL without necessarily changing the content it returns. Whether that change produces a separate cached response depends on the cache’s key and configuration. This guide explains how query parameters interact with browser and shared caches, what Cache-Control and Vary do, and how to check whether a parameter is safe to ignore.
Key Takeaways
- HTTP caches generally use the request method and target URI as the primary cache key. Since a query string is part of the URI, different query strings can identify different cached responses.
- That is not a universal rule for every cache: browsers, CDNs, proxies, and servers may use different or customized cache keys.
- A parameter used only to version an asset can be useful for cache busting. A parameter that changes the content must not be ignored when constructing a cache key.
Cache-Controlsets caching and revalidation rules.Varytells caches that selected request headers can distinguish response variants; it is not a query-string setting.
How a cache key treats a query string
A cache key is the information a cache uses to decide whether a stored response matches a new request. HTTP caching specifications define a primary cache key based on the request method and target URI. The URI includes its query component, so these requests may have separate entries:
https://example.com/products?sort=price
https://example.com/products?sort=rating
The responses might be identical, but the cache cannot infer that from the URLs alone. Conversely, a cache can be configured to ignore some or all query parameters, or to use only selected parameters. Browser caches and shared caches such as CDNs or proxies do not necessarily use identical policies.
Other details of cache-key construction can also vary, including URI normalization and whether request headers contribute to the key. Treat a URL change as a potential cache-key change, not as a guarantee that every cache will store a distinct response.
Cache-busting parameters and content parameters
A cache-busting parameter changes the URL to indicate a new version of an otherwise static asset. For example:
/assets/site.css?v=4
/assets/site.css?v=5
If the cache key includes v, the second URL can avoid reusing the first URL’s stored response. This is useful when deploying a changed file, but it works only if the relevant caches preserve that parameter in their keys. A cache configured to ignore v may still serve the earlier response.
A content parameter changes what the server returns. Examples include ?page=2, ?language=fr, or ?sort=price. If the response varies with such a parameter, a cache that removes or ignores it could serve the wrong content to a later request. If you configure a CDN or proxy to exclude parameters from its key, exclude only parameters that genuinely do not affect the response.
Parameters can also carry tracking data that does not affect the page itself, such as a campaign identifier. Some cache configurations can disregard selected tracking parameters to improve reuse, but doing so safely requires understanding the application and the cache’s exact key rules. Do not assume every parameter with a familiar name is harmless to ignore.
What Cache-Control and Vary do
Cache-Control controls whether and how a response can be stored and reused. It does not, by itself, define which query parameters a particular CDN includes in its cache key.
For example, a versioned static asset might use:
Cache-Control: public, max-age=31536000, immutable
This permits shared caching and allows a fresh response to be reused for the stated period. Long freshness is appropriate only if a changed asset gets a new URL, such as a new version parameter or a filename containing a content hash.
For a response that can be stored but should be checked with the origin before reuse, a server might send:
Cache-Control: no-cache
no-cache does not mean “do not store”; it requires revalidation before reuse. By contrast, no-store tells caches not to store the response. These directives govern reuse and storage, not whether a query string is part of a cache key.
Vary handles variation by request headers. For example:
Vary: Accept-Language
This tells a cache that the response may differ according to the request’s Accept-Language header. Vary is not a way to declare that a response varies by a query parameter: query parameters are part of the target URI used in the primary key. Use Vary for relevant request headers, and ensure any shared cache’s key accounts for the parameters that affect the response.
A practical way to investigate
- Compare the actual URLs. Record the path and complete query string for each request. Check whether the parameter is only for versioning or changes the returned content.
- Inspect the response headers. Look at
Cache-Control,Vary,ETag, andLast-Modified. These help explain freshness and validation, but do not necessarily reveal a CDN’s complete cache-key configuration. - Check the cache in question. Review browser developer tools and, for a CDN or proxy, its cache-key and query-string settings. Do not assume results from one layer apply to another.
- Test repeated requests. Request the same URL more than once, then compare it with a URL whose query value differs. Use the same method and relevant request headers. Observe whether the response changes and whether cache indicators change.
- Interpret indicators cautiously. Headers such as
Agecan indicate that a shared cache has served a response, while headers likeX-Cacheare implementation-specific. Browser developer tools may report memory or disk cache use. No single indicator describes every cache layer.
For a quick look at response headers, you can use curl:
curl -sS -D - -o /dev/null 'https://example.com/products?sort=price'
Repeat with the alternate URL and compare the status and headers. This checks the response visible to that command; it does not prove how a particular browser or CDN will behave. A HEAD request may also be handled differently from a GET, so use the request method relevant to the page or asset you are investigating.
Common Mistakes
- Assuming a unique query string always bypasses caches. It works only when the relevant cache distinguishes that URL. Some configurations normalize or ignore selected parameters.
- Ignoring a parameter that changes the response. This can cause users to receive content for a different page, locale, or sort order.
- Treating
no-cacheasno-store. The former allows storage but requires validation before reuse; the latter prohibits storage. - Using
Varyfor query parameters.Varydescribes request-header differences. Query parameters belong to the request URI. - Testing only one cache layer. A browser, reverse proxy, CDN, and origin may each have separate behavior and settings.
Best Practices
- Use versioned URLs for static assets whose contents change, and configure the relevant caches to retain the version in their keys.
- Keep parameters that affect the response in the cache key.
- Exclude parameters only after confirming that they do not change the representation or access control outcome.
- Set explicit
Cache-Controlpolicies that match how fresh the response may be and whether it is safe to store in shared caches. - Use
Varywhen response selection depends on request headers, and test the resulting variants. - Check browser and shared-cache behavior separately after changing cache rules.
Conclusion
Query parameters can affect caching because they are part of the request URI, but actual cache-key behavior depends on the cache and its configuration. Identify which parameters change the response, inspect the applicable cache rules, and use Cache-Control and Vary for their distinct purposes.
References
- RFC 9111: HTTP Caching — HTTP caching rules, cache keys, freshness, and validation.
- MDN: HTTP caching — Practical overview of browser and shared-cache behavior and caching headers.
