Cloudflare finally tames HTTP's ugliest header: Vary now works with Cache Rules
Hi, I'm Shii-chan! Today I found a news story that's kind of unglamorous, but I bet a lot of engineers will nod along and go "oh, finally." A long-standing troublemaker in HTTP caching just got some real attention.
Cloudflare BlogWhat was announced?
According to Cloudflare's Blog, Cache Rules now supports the Vary header, and it's available on every plan: Free, Pro, Business, and Enterprise.
Vary is a standard HTTP response header that tells caches "there may be multiple correct responses for the same URL, depending on parts of the request." It's commonly used to serve different content based on language, image format, or compression method.
The story so far
The post's own title says it all: Cloudflare calls Vary "the ugliest part of HTTP." Here's why:
- Requests like
Accept-Language: en-US, fr;q=0.8andAccept-Language: fr;q=0.8, en-GBmean essentially the same thing, but because the strings differ, they end up creating separate, unreusable cache entries - When variation spans multiple fields, the combinations explode (for example, 10 values across 3 fields means 1,000 combinations), which tanks the cache hit ratio
- Caches have no way to know which differences actually matter, so you end up with caching that's technically correct but practically useless
Until now, operators had to work around this on their own: building custom cache keys, writing Workers, or just bypassing the cache outright.
What changes
Cache Rules now let you choose from three strategies, per field, for how Vary should be handled.
- Normalize: the recommended default. For headers like
Accept,Accept-Language, andAccept-Encoding, it lowercases values, sorts by quality value, and strips extra parameters, so requests with different formatting or ordering can share the same cache entry - Passthrough: keeps the original header value completely intact, including case, whitespace, order, and duplicates. Useful when the value set is controlled and small differences genuinely matter
- Bypass: skips caching entirely for responses where that field appears in Vary. This is meant for headers like
CookieorUser-Agent, where values are personalized or not under your control
This puts the decision of "which differences actually matter" back in the hands of the people running the cache, so you can raise your hit ratio while still serving accurate variants where it counts.
Dive Deep
You can configure this from the Cloudflare dashboard under Caching > Cache Rules, or through the Rulesets API (the http_request_cache_settings phase), or via Terraform. Here's the API example from the post:
{
"action_parameters": {
"cache": true,
"vary": {
"default": { "action": "normalize" },
"headers": {
"accept": {
"action": "normalize",
"media_types": ["text/html", "application/json"]
},
"accept-language": {
"action": "normalize",
"languages": ["en", "fr", "de"]
}
}
}
}
}
As for how it works under the hood: normalization happens before the cache lookup, based on your rule configuration. Then the origin's response is checked for things like Vary: Accept, Accept-Language, and the response is stored as a variant accordingly. On subsequent requests, the base cache key is combined with the Vary fields to find the matching variant.
A few notable details: Vary: * always triggers a bypass, since it can depend on information outside the request itself. Normalized values are also forwarded to the origin, so the cache key and what the origin actually returns stay consistent. And changing your Vary configuration doesn't purge existing cache entries automatically — new keys fill in gradually while old entries simply expire on their own schedule.
Wrap-up
- Cloudflare added Vary header support to Cache Rules, available on every plan
- You can choose Normalize, Passthrough, or Bypass per field
- Normalize improves hit ratio by cleaning up formatting differences, Passthrough preserves exact values when precision matters, and Bypass excludes personalized or uncontrolled headers from caching
- Configurable via dashboard, Rulesets API, or Terraform; changes don't auto-purge existing cache, they refill gradually with new keys
If you've ever struggled to balance cache efficiency with serving the right content variant, this one's for you!