<- blog

Vary Caching Needs Content Contracts

Cloudflare Cache Rules now honor Vary. That helps multilingual and format-aware pages, but only if teams control variant keys.

#performance#seo#reliability

Cloudflare shipped a practical caching change on 2 July: Cache Rules can now cache multiple versions of the same URL using the origin's Vary header. The feature lets Cloudflare keep separate cached responses for the same URL when the origin varies by headers such as Accept-Language or Accept, with options to normalize, pass through, or bypass each varied header.

That sounds like CDN plumbing. For many business sites, it is actually a content and measurement contract. The same product page, landing page, quote funnel, or help article may now be cached correctly across languages, formats, and client capabilities without forcing every variant to bypass cache.

Why this matters beyond performance

The common caching trade-off has been blunt: either cache one generic response aggressively, or bypass cache when the page depends on request headers. That is painful for sites that need correct variants:

  • English and non-English content selected by Accept-Language;
  • HTML, JSON, or lightweight responses selected by Accept;
  • image or document formats negotiated by the client;
  • bot, crawler, or app client responses that need different representations;
  • edge-rendered content where the URL stays stable but the response is not identical.

When the CDN can understand the origin's Vary header, teams get a better option: cache the variants that are safe, normalize noisy headers that should collapse to the same key, and bypass the variants that would explode cardinality or leak personalised content.

The business upside is faster pages without giving every customer, crawler, or integration the wrong version.

The contract: which headers are allowed to split a page?

Before enabling this on important routes, write down which request headers are allowed to create a separate cached response. Treat it like schema design for the edge cache.

route: /services/emergency-plumbing
cache_variants:
  accept-language:
    action: normalize
    allowed_outcomes:
      - en
      - en-au
  accept:
    action: normalize
    allowed_outcomes:
      - text/html
      - application/json
never_vary_on:
  - cookie
  - authorization
  - user-agent
  - x-customer-id
review_if_variant_count_exceeds: 4

The exact values will differ by site. The useful part is the boundary: only headers with a clear content reason should split the cache. Everything else should be normalized, bypassed, or removed from the response's Vary header.

Normalize first, pass through rarely

Cloudflare's changelog describes three actions for headers named in Vary: normalize, passthrough, and bypass. For small teams, the default posture should be conservative:

Action Practical use Risk
normalize Collapse equivalent language or accept values into fewer cache keys. You must confirm the normalized buckets match real content variants.
passthrough Preserve the raw header value when byte-for-byte differences really matter. Header values can create too many cache entries.
bypass Avoid caching when the header is too personal, too noisy, or unsafe. Performance is lower, but correctness is protected.

Most marketing, ecommerce, and local-service pages should start with normalization. Pass-through caching is powerful, but it can quietly turn one URL into many edge objects if the header contains detailed client preferences.

SEO and analytics need the same map

Variant caching should not create a second reality for search crawlers or analytics. If /product/widget can produce multiple cached responses, teams should know:

  1. which variant Googlebot receives;
  2. whether canonical tags, hreflang tags, structured data, and Open Graph metadata are consistent;
  3. whether analytics events use the same page identity across variants;
  4. whether A/B tests or personalisation are accidentally being cached as public variants;
  5. whether the sitemap points to stable URLs or relies on hidden header negotiation.

This is especially important for multilingual pages. Accept-Language can improve first response relevance, but it should not replace deliberate URL and metadata strategy where SEO matters. A cached language variant can be technically correct and still confuse reporting if the team has not decided how page identity is measured.

Add a variant smoke test to release checks

For revenue pages, test the cache contract directly. A simple smoke test can request the same URL with the expected headers, then compare status, cache headers, content markers, and metadata.

URL="https://example.com/product/widget"

curl -I -H 'Accept-Language: en-AU,en;q=0.8' "$URL"
curl -I -H 'Accept-Language: fr-FR,fr;q=0.8' "$URL"
curl -I -H 'Accept: text/html' "$URL"
curl -I -H 'Accept: application/json' "$URL"

For each variant, record what should be different and what must stay the same. Different language copy may be expected. Different canonical URLs, missing structured data, inconsistent prices, or different lead-tracking IDs probably are not.

Watch the headers that should never vary

The dangerous cases are rarely the obvious language or format headers. They are accidental Vary values that come from frameworks, middleware, or upstream services. Be careful with headers that can encode identity, experiments, device quirks, or high-cardinality client details.

For practical sites, consider a blocklist review for:

  • Cookie and Authorization;
  • customer, session, account, or CRM identifiers;
  • raw User-Agent values;
  • geolocation headers with fine-grained location;
  • experiment assignment headers;
  • internal debugging headers.

If those appear in a response's Vary header, the safe answer is usually not "cache more versions". It is to remove the accidental variation or bypass cache for that path.

The useful implementation order

Roll this out where the content model is clear, not where the cache is most confusing.

  1. Pick one route family, such as help articles, product detail pages, or location landing pages.
  2. List the headers that intentionally change the response.
  3. Choose normalize, passthrough, or bypass for each one.
  4. Add smoke tests for the expected variants.
  5. Check SEO metadata and analytics identity across variants.
  6. Monitor origin traffic, cache hit ratio, and variant count after release.

Cloudflare making Vary easier to use at the cache layer is a good platform improvement. The operational lesson is broader: content negotiation belongs in a contract, not in accidental headers. If a URL can produce multiple public versions, define the allowed versions before the edge starts remembering them.

Need technical help?

I'm a software engineer who builds web apps, APIs, and AI tooling. If you've got a project or a problem to talk through, book a free 30-minute call.

Book time with me ->