A cache key decides whether two requests may reuse the same stored response. A typical CDN starts with the request scheme, host, path, and query string. It may also include selected headers or cookies. The Vary response header is the HTTP mechanism that tells a cache which request headers selected a representation.

The safe goal is simple: requests that should receive the same bytes should share a key, while requests that require different bytes must not collide. A key that is too narrow can expose the wrong response. A key that is too broad creates many variants, lowers the cache hit ratio, and increases origin traffic.

How Vary changes cache matching

Suppose an origin returns:

Vary: Accept-Encoding

The cache can store compressed and uncompressed representations for the same URL. Before reusing one, it compares the current request’s Accept-Encoding value with the request that produced the stored response.

RFC 9111, section 4.1 defines this matching behavior. CDN controls may normalize values or add other fields to a vendor-specific key, but they do not change the origin’s obligation to describe content negotiation accurately.

What Vary: * means

Vary: * means that unlisted aspects of the request may have selected the response. A cache cannot determine whether a later request is equivalent, so it cannot reuse that stored response without forwarding the request to the origin.

This is different from Cache-Control: no-store. Vary: * prevents normal reuse; no-store tells caches not to store the response. If a response is intentionally uncacheable, an explicit cache-control policy is usually clearer.

Query strings

Including the complete query string is safe but can fragment the cache. Tracking parameters such as utm_source often do not change the response. Search, filters, signatures, language, and version parameters often do.

Use an allowlist or denylist only after classifying each parameter:

Parameter typeTypical treatmentReason
Content selectorIncludeDifferent values can produce different bytes.
Version identifierIncludeEach version is a separate object.
Authorization signatureFollow the provider’s signed-request designRemoving it can bypass access rules.
Analytics campaign tagExclude after verificationIt usually does not change the representation.
Unknown parameterInclude until classifiedCorrectness is more important than hit ratio.

Normalize parameter order if the application treats different orders as equivalent. Do not normalize repeated parameters unless the application defines their ordering and duplication semantics.

Cookies

Using an entire Cookie header in the key usually creates excessive variants because analytics, consent, and session cookies change independently. Ignoring all cookies is unsafe when any cookie affects the response.

A safer design is to separate public and personalized routes. For a public route, remove irrelevant cookies before the cache or configure the CDN to key on a small named set. For a personalized route, use Cache-Control: private or no-store unless shared caching has been designed and tested explicitly.

Never cache a personalized response under a public key. Test logged-in, logged-out, administrative, regional, and experiment states before enabling shared caching.

Language and content negotiation

Vary: Accept-Language is correct when the origin selects a language from that header, but raw browser values create many combinations. Prefer stable language URLs such as /en/ and /nl/ where product requirements allow them. They make cache identity, canonical URLs, analytics, and sharing easier to reason about.

If header negotiation is required, map the many possible request values to a small supported language set before they reach the cache key. Return Vary: Accept-Language so downstream caches understand that the header matters.

Device variants

Avoid Vary: User-Agent. User-agent strings have extremely high cardinality and change over time. Responsive HTML and CSS usually allow one representation to serve all devices.

When different bytes are necessary, classify devices into a small documented set at one trusted layer. Add only that normalized classifier to the cache key. Verify that the origin and CDN use the same classification; otherwise the cache can serve a mobile object to a desktop request or the reverse.

CDN-specific cache keys

Many CDNs can include or exclude query parameters, cookies, and headers independently of Vary. These controls can improve efficiency, but they also create policy outside the origin response.

Keep the policy in version control and document:

  • the base key fields;
  • included and excluded query parameters;
  • included cookies and headers;
  • normalization rules;
  • routes that bypass shared caching;
  • how purge commands map to variants.

In a multi-CDN deployment, configure equivalent keys at every provider. A difference in one header or parameter can produce inconsistent content and different hit ratios.

Cardinality budget

Variant counts multiply. Three languages, two encodings, two device classes, and four experiment groups can create 48 objects for one URL. Most of those objects may receive too little traffic to remain warm.

Before adding a dimension, estimate its distinct values and request distribution. Prefer dimensions with a small, stable set and clear user value. Remove fields that do not change the response.

Safe rollout checklist

  1. Record the current key and hit ratio.
  2. List every input that can change the response.
  3. Classify routes as public, private, or mixed.
  4. Test representative requests at the origin without the CDN.
  5. Enable the new key on a staging hostname or small traffic segment.
  6. Compare response bodies, Age, Vary, and provider cache-status headers.
  7. Test authentication boundaries and experiment variants.
  8. Purge affected objects if the old and new key spaces can overlap incorrectly.
  9. Watch hit ratio, origin requests, latency, and unexpected variant growth.

Use Cache-Control and TTLs to define storage and freshness. Use purging to plan invalidation when key rules change.