The Vary response header lists the request headers that affected the response, so caches store a separate copy for each combination of those header values. If you omit a header that changes your output, a shared cache can serve one user's variant to another. If you list too many, the cache hit rate collapses.
What Vary does
MDN describes it plainly: including Vary ensures that responses are cached separately based on the headers it lists. In effect those request headers become part of the cache key. It is mostly used with content negotiation.
HTTP/1.1 200 OK
Content-Type: text/css
Content-Encoding: br
Vary: Accept-Encoding
Without Vary: Accept-Encoding, a cache could hand Brotli bytes to a client that only understands gzip. MDN also recommends the same Vary value on every response for a URL, including 304 responses and the default response.
How a cache applies it
RFC 9111 says a stored response is reused only if the request headers named in Vary match those of the original request. A Vary value of * never matches, which MDN reads as a signal that factors other than request headers shaped the response, so it is effectively uncacheable. When several stored responses match, the cache picks the most recent by Date, or ranks them if a mechanism such as quality values applies.
Mistakes to avoid
- Leaving out a header your code reads. If the response changes with Accept-Language and you do not list it, a shared cache can store one language and serve it to everyone.
- Varying on too much. Each distinct combination of values creates another cached entry. Headers with many possible values, like User-Agent or Cookie, split the cache into many pieces that are rarely reused.
- Caching personalized pages at all. If the response depends on a user, prefer
Cache-Control: privateorno-storeover a cookie based Vary. See the Cache-Control cheat sheet. - Inconsistent Vary across responses. A 304 or an error response with a different Vary can confuse caches.
- Reflecting unkeyed headers. Any header that changes output but is not in the key is a poisoning risk, which is why CDN poisoning guidance often starts here. Read CDN cache poisoning prevention.
A short audit
- List every request header your application and middleware read when building a response.
- Compare that list with the Vary header you send.
- Remove any header from Vary that does not change the output.
- Test through your CDN with two clients that differ in one header, and confirm each gets the right variant.
Where Safeguard fits
Safeguard does not configure your caches. It scans dependencies and SBOMs for known vulnerabilities, including in the web frameworks and middleware that set these headers, and offers policy gates for pull requests. A free scan is at gold.safeguard.sh/scan.
Quick check
What does Vary: * mean?
Per MDN, factors other than request headers influenced the response, which implies it is uncacheable.
Why is Vary: Cookie often a poor choice?
Each user has a different cookie value, so almost nothing is shared. Mark personalized responses private or no-store instead.
Sources
Last reviewed: 19 October 2026.