Build1 publisher2 min readPublished
Cloudflare hands the Vary normalization call to whoever writes the Cache Rule
Support for the Vary header has landed in Cloudflare's Cache Rules on every plan. The judgement it moves to the edge is how much of a request header's variation deserves a cache entry of its own.
The Engineer · Build desk

What happened
- Vary support is now live in Cloudflare's Cache Rules on every plan, with the origin still naming the request headers that may change a response and the rule author choosing how each one is handled.
- Each named header gets one of three treatments: normalize known negotiation headers, pass exact values through when the small differences matter, or bypass cache when the variation is too unpredictable.
- Cloudflare's example has an origin serving only English, French and German receiving two differently ordered Accept-Language values that both prefer English and map to the same English response.
- A cache comparing those raw strings cannot assume the two requests are equivalent, so it can keep two variants whose bodies contain identical bytes.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision The rule author now needs something the origin team carries in its head: the list of distinct responses each endpoint actually produces. Without it, there is no basis for choosing normalize over pass-through.
- cost Duplicate variants are paid for twice. They occupy edge capacity while nothing reuses them, then bill the origin for the requests a single hot entry would have absorbed.
- constraint Enumeration is the ceiling. A header whose value set the operator cannot list, a per-visitor cookie for instance, has only two honest treatments left, and neither of them recovers a hit.
- capability Teams that cannot get an origin header changed can now collapse or drop variation at the edge, which puts cache tuning inside reach of people who do not own the application.
The gap this works on is informational. An origin knows its catalogue endpoint emits three bodies. HTTP gives it no way to tell a cache that thousands of possible `Accept-Language` strings collapse into those three, and Vary only names the fields that may matter [4][11].
Cardinality decides what that costs. Ten possible values on one field make ten variants; ten values across three fields can make 1,000 combinations [12]. Cloudflare's post points out that real headers are worse. `User-Agent` values are numerous, cookies can be unique to one visitor, and preference headers differ in ordering, in formatting (spaces and tabs matter) and in quality values [13].
Put the post's two examples end to end. A response varies on three fields of ten values each, and the origin behind it emits three distinct bodies. That fills 1,000 cache entries with three byte sequences, so 997 of the entries are duplicates [15]. Each entry draws on average a thousandth of the requests one normalized entry would draw [16]. Cloudflare calls that outcome a cache that is perfectly correct and almost permanently cold [14]. The post does not give hit-ratio figures [17].
The error in the other direction is worse than a cold cache. In Cloudflare's worked example, `GET /catalog` with `Accept: text/html` returns HTML with `Cache-Control: public, max-age=3600` and `Vary: Accept`, while the same URL with `Accept: application/json` correctly returns JSON [7]. Ignore the Vary header and whichever response is cached first goes to both clients, so the API client's JSON parser is handed markup [8].
Credit for the framing: the announcement leads with the header's reputation, quoting a description of Vary as "the ugliest part of HTTP that we haven't yet improved" [5] and relaying a second one that calls it a "horrible, kludgy mechanism" with "pretty abysmal interoperability" across intermediaries [6].
Whether normalization pays turns on a ratio Cloudflare cannot see from the edge: distinct responses your origin emits, over distinct header values your clients send. Three over several thousand, and normalizing `Accept-Language` against your supported list is most of your hit ratio. Near one, and there is nothing to collapse, so the only thing a normalizing rule changes is which client gets the wrong bytes. I would write down the list of representations each endpoint actually produces before editing the rule.
What to watch
- Whether Cloudflare documents the per-header normalization semantics, in particular how it treats q-values, tag ordering and whitespace.
- Which headers Cloudflare classes as "known negotiation headers" eligible for normalization.
- Measured hit-ratio changes from sites that move Accept-Language from exact pass-through to normalized.