The No-Vary-Search HTTP Caching Extension
draft-ietf-httpbis-no-vary-search-08
| Document | Type | Active Internet-Draft (httpbis WG) | |
|---|---|---|---|
| Authors | Domenic Denicola , Jeremy Roman , Nidhi Jaju | ||
| Last updated | 2026-08-12 | ||
| Replaces | draft-wicg-http-no-vary-search | ||
| RFC stream | Internet Engineering Task Force (IETF) | ||
| Intended RFC status | Proposed Standard | ||
| Formats | |||
| Reviews |
GENART IETF Last Call review
(of
-06)
by Mallory Knodel
Ready w/issues
ARTART IETF Last Call Review due 2026-08-07
Incomplete
|
||
| Additional resources | Mailing list discussion | ||
| Stream | WG state | Submitted to IESG for Publication | |
| Document shepherd | Tommy Pauly | ||
| Shepherd write-up | Show Last changed 2026-06-03 | ||
| IESG | IESG state | IESG Evaluation | |
| Action Holder | |||
| Consensus boilerplate | Yes | ||
| Telechat date |
On agenda of 2026-08-20 IESG telechat
Needs 4 more YES or NO OBJECTION positions to pass. |
||
| Responsible AD | Mike Bishop | ||
| Send notices to | tpauly@apple.com | ||
| IANA | IANA review state | Version Changed - Review Needed | |
| IANA expert review state | Expert Reviews OK |
draft-ietf-httpbis-no-vary-search-08
HyperText Transfer Protocol D. Denicola
Internet-Draft J. Roman
Intended status: Standards Track N. Jaju, Ed.
Expires: 13 February 2027 Google LLC
12 August 2026
The No-Vary-Search HTTP Caching Extension
draft-ietf-httpbis-no-vary-search-08
Abstract
This specification defines an extension to HTTP Caching, changing how
the URI query component impacts caching. It introduces the "No-Vary-
Search" response header field, which allows origin servers to signal
to caches that certain parts of the query component do not
semantically affect the served response and can be ignored for cache
matching purposes.
About This Document
This note is to be removed before publishing as an RFC.
The latest revision of this draft can be found at https://httpwg.org/
http-extensions/draft-ietf-httpbis-no-vary-search.html. Status
information for this document may be found at
https://datatracker.ietf.org/doc/draft-ietf-httpbis-no-vary-search/.
Discussion of this document takes place on the HTTP Working Group
mailing list (mailto:ietf-http-wg@w3.org), which is archived at
https://lists.w3.org/Archives/Public/ietf-http-wg/. Working Group
information can be found at https://httpwg.org/.
Source for this draft and an issue tracker can be found at
https://github.com/httpwg/http-extensions/labels/no-vary-search.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Denicola, et al. Expires 13 February 2027 [Page 1]
Internet-Draft No-Vary-Search August 2026
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 13 February 2027.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4
3. HTTP header field definition . . . . . . . . . . . . . . . . 5
4. Data model . . . . . . . . . . . . . . . . . . . . . . . . . 5
5. Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
5.1. Parse a URL variation config . . . . . . . . . . . . . . 6
5.2. Obtain a URL variation config . . . . . . . . . . . . . . 7
5.2.1. Examples . . . . . . . . . . . . . . . . . . . . . . 8
5.3. Parse a key . . . . . . . . . . . . . . . . . . . . . . . 10
5.3.1. Examples . . . . . . . . . . . . . . . . . . . . . . 10
6. Comparing . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 13
7. Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
8. Security Considerations . . . . . . . . . . . . . . . . . . . 16
9. Privacy Considerations . . . . . . . . . . . . . . . . . . . 17
10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18
10.1. HTTP Field Names . . . . . . . . . . . . . . . . . . . . 18
10.2. No-Vary-Search Dictionary Keys Registry . . . . . . . . 18
11. References . . . . . . . . . . . . . . . . . . . . . . . . . 19
11.1. Normative References . . . . . . . . . . . . . . . . . . 19
11.2. Informative References . . . . . . . . . . . . . . . . . 20
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 20
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 21
Denicola, et al. Expires 13 February 2027 [Page 2]
Internet-Draft No-Vary-Search August 2026
1. Introduction
HTTP caching [HTTP-CACHING] is based on reusing resources which match
across a number of cache keys, with the most important one being the
presented target URI (Section 7.1 of [HTTP]). However, sometimes
multiple URIs can represent the same resource. This leads to caches
not always being as helpful as they could be: if the cache contains a
response under one URI, but the response is then requested under
another, the cached version will be ignored.
The "No-Vary-Search" response header field defines a caching
extension, as described in Section 4 of [HTTP-CACHING], that tackles
a specific subset of this general problem, for when different URIs
that differ only in their query component identify the same resource.
It allows resources to declare that some or all parts of the query
component do not semantically affect the served response, and thus
can be ignored for cache matching purposes. This is achieved by
interpreting the query component as a sequence of parameters encoded
using the application/x-www-form-urlencoded format [WHATWG-URL]. For
example, if the order of the parameters within the query component
does not affect which resource is identified, this is indicated using
No-Vary-Search: key-order
If specific query parameters (e.g., ones indicating something for
analytics) do not semantically affect the served resource, this is
indicated using
No-Vary-Search: params=("utm_source" "utm_medium" "utm_campaign")
And if the resource instead wants to take an allowlist-based
approach, where only certain known query parameters semantically
affect the served response, they can use
No-Vary-Search: except=("productId")
Note that "cache busting", the practice of changing a part of the
query component to create a distinct cache key and force retrieval of
a newer response, can be made ineffective by the "No-Vary-Search"
response header field.
Section 3 defines the new "No-Vary-Search" response header field,
using the [STRUCTURED-FIELDS] framework. Section 4 and Section 5
illustrate the data model for how the field value can be represented
in specifications, and the process for parsing the raw output from
the structured field parser into that data model. Section 6 gives
the key algorithm for comparing if two URLs are equivalent under the
influence of the header field; notably, it leans on the decomposition
Denicola, et al. Expires 13 February 2027 [Page 3]
Internet-Draft No-Vary-Search August 2026
of the query component into keys and values given by the application/
x-www-form-urlencoded (https://url.spec.whatwg.org/#concept-
urlencoded) format specified in [WHATWG-URL]. (As such, this header
field is not useful for URLs whose query component does not follow
that format.) Finally, Section 7 explains how to extend Section 4 of
[HTTP-CACHING] to take this new equivalence into account.
From a deployment perspective, this extension is implemented by HTTP
caches, including browser caches, content delivery networks, and
forward proxies. Origin servers send the "No-Vary-Search" response
header field to provide instructions to these caches. Caches that
implement this extension use these instructions to determine when a
previously stored response can be safely reused for a new request,
even if the query components of the target URIs differ.
2. Conventions and Definitions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
In this document, the terms "URI" and "URL" are used interchangeably,
depending on context. "URI" is used in the context of [URI], [HTTP],
and [HTTP-CACHING], whereas "URL" is used in the context of the
algorithms specified in [WHATWG-URL].
The term "query parameters" in this document refers to the keys and
values resulting from parsing a URL's query component using the
application/x-www-form-urlencoded
(https://url.spec.whatwg.org/#concept-urlencoded) format
[WHATWG-URL].
This document also adopts some conventions and notation typical in
WHATWG and W3C usage, especially as it relates to algorithms. See
[WHATWG-INFRA], and in particular:
* its definition of lists, including the list literal notation « 1,
2, 3 ».
* its definition of strings, including their representation as code
units.
(Other concepts used are called out using inline references.)
Denicola, et al. Expires 13 February 2027 [Page 4]
Internet-Draft No-Vary-Search August 2026
3. HTTP header field definition
The "No-Vary-Search" response header field is a structured field
[STRUCTURED-FIELDS] whose value MUST be a dictionary (Section 3.2 of
[STRUCTURED-FIELDS]).
It has the following constraints:
* If present, the key-order entry's value MUST be a boolean
(Section 3.3.6 of [STRUCTURED-FIELDS]).
* If present, the params entry's value MUST be an inner list of
strings (Section 3.1.1 of [STRUCTURED-FIELDS]).
* If present, the except entry's value MUST be an inner list of
strings (Section 3.1.1 of [STRUCTURED-FIELDS]).
* The except entry MUST NOT be present if the params entry is also
present.
The dictionary MAY contain entries whose keys are not one of key-
order, params, and except, but their meaning is not defined by this
specification. Implementations of this specification will ignore
such entries (but future documents might assign meaning to such
entries). Future extensions to this dictionary MUST NOT restrict the
set of URIs that are considered equivalent; they can only expand it.
If a future extension requires restricting equivalence, it MUST be
deployed as a new HTTP header field to ensure safety.
The "No-Vary-Search" response header field is set by origin servers.
Intermediaries MUST NOT insert, delete, or modify the field's value
unless they are acting as the origin server for that response.
| A parsing algorithm is defined in Section 5.2.
4. Data model
A _URL variation config_ consists of the following:
no-vary params
either the special value *wildcard* or a list of strings
vary params
either the special value *wildcard* or a list of strings
vary on key order
a boolean
Denicola, et al. Expires 13 February 2027 [Page 5]
Internet-Draft No-Vary-Search August 2026
The _default URL variation config_ is a URL variation config whose
no-vary params is an empty list, vary params is *wildcard*, and vary
on key order is true.
The obtain a URL variation config algorithm (Section 5.2) ensures
that all URL variation configs obey the following constraints:
* vary params is a list if and only if the no-vary params is
*wildcard*; and
* no-vary params is a list if and only if the vary params is
*wildcard*.
5. Parsing
5.1. Parse a URL variation config
To _parse a URL variation config_ given _value_:
1. If _value_ is null, then return the default URL variation config.
2. Let _result_ be a new URL variation config.
3. Set _result_'s vary on key order to true.
4. If _value_["key-order"] exists:
1. If _value_["key-order"] is not a boolean, then return the
default URL variation config.
2. Set _result_'s vary on key order to the boolean negation of
_value_["key-order"].
5. If both _value_["params"] and _value_["except"] exist, then
return the default URL variation config.
6. If neither _value_["params"] nor _value_["except"] exists:
1. Set _result_'s no-vary params to an empty list.
2. Set _result_'s vary params to *wildcard*.
7. If _value_["params"] exists:
1. If _value_["params"] is not an inner list, then return the
default URL variation config.
Denicola, et al. Expires 13 February 2027 [Page 6]
Internet-Draft No-Vary-Search August 2026
2. If any item in _value_["params"] is not a string, then return
the default URL variation config.
3. Set _result_'s no-vary params to the result of applying parse
a key (Section 5.3) to each item in _value_["params"].
4. If any item in _result_'s no-vary params is an error, then
return the default URL variation config.
5. Set _result_'s vary params to *wildcard*.
8. Otherwise, if _value_["except"] exists:
1. If _value_["except"] is not an inner list, then return the
default URL variation config.
2. If any item in _value_["except"] is not a string, then return
the default URL variation config.
3. Set _result_'s vary params to the result of applying parse a
key (Section 5.3) to each item in _value_["except"].
4. If any item in _result_'s vary params is an error, then
return the default URL variation config.
5. Set _result_'s no-vary params to *wildcard*.
9. Return _result_.
| In general, this algorithm is strict and tends to return the
| default URL variation config whenever it sees something it
| doesn't recognize. This is because the default URL variation
| config behavior will just cause fewer cache hits, which is an
| acceptable fallback behavior.
| The input to this algorithm is generally obtained by parsing a
| structured field (Section 4.2 of [STRUCTURED-FIELDS]) using
| field_type "dictionary".
5.2. Obtain a URL variation config
To _obtain a URL variation config_ given an HTTP response
(Section 3.4 of [HTTP]) _response_:
1. Let _fieldValue_ be the result of parsing the "No-Vary-Search"
response header field from _response_ as a Dictionary
(Section 4.2 of [STRUCTURED-FIELDS]). If parsing fails or the
field is absent, let _fieldValue_ be null.
Denicola, et al. Expires 13 February 2027 [Page 7]
Internet-Draft No-Vary-Search August 2026
2. Return the result of parsing a URL variation config (Section 5.1)
given _fieldValue_.
5.2.1. Examples
The following illustrates how various inputs are parsed, in terms of
their impact on the resulting no-vary params and vary params:
+=================+==============================+
| Input | Result |
+=================+==============================+
| No-Vary-Search: | no-vary params: (empty list) |
| key-order | vary params: *wildcard* |
| | vary on key order: false |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: « "a" » |
| params=("a") | vary params: *wildcard* |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: *wildcard* |
| except=("x") | vary params: « "x" » |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: (empty list) |
| params=() | vary params: *wildcard* |
+-----------------+------------------------------+
| No-Vary-Search: | no-vary params: *wildcard* |
| except=() | vary params: (empty list) |
+-----------------+------------------------------+
Table 1
The following inputs are all invalid and will cause the default URL
variation config to be returned:
Denicola, et al. Expires 13 February 2027 [Page 8]
Internet-Draft No-Vary-Search August 2026
+============================+==============================+
| Input | Explanation |
+============================+==============================+
| No-Vary-Search: key- | key-order expects a boolean, |
| order="not a boolean" | not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | params expects an inner |
| params="not an inner list" | list, not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | params items must be strings |
| params=(not-a-string) | (tokens are invalid) |
+----------------------------+------------------------------+
| No-Vary-Search: params=?0 | params expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
| No-Vary-Search: params=?1 | params expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
| No-Vary-Search: params=?1, | params and except cannot |
| except=("x") | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: | params and except cannot |
| params=("a"), except=("x") | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: params=(), | params and except cannot |
| except=() | both be present |
+----------------------------+------------------------------+
| No-Vary-Search: | except expects an inner |
| except="not an inner list" | list, not a string |
+----------------------------+------------------------------+
| No-Vary-Search: | except items must be strings |
| except=(not-a-string) | (tokens are invalid) |
+----------------------------+------------------------------+
| No-Vary-Search: except=?1 | except expects an inner |
| | list, not a boolean |
+----------------------------+------------------------------+
Table 2
The following inputs are valid, but somewhat unconventional. They
are shown alongside their more conventional form.
Denicola, et al. Expires 13 February 2027 [Page 9]
Internet-Draft No-Vary-Search August 2026
+==============================+===========================+
| Input | Conventional form |
+==============================+===========================+
| No-Vary-Search: key-order=?1 | No-Vary-Search: key-order |
+------------------------------+---------------------------+
| No-Vary-Search: | No-Vary-Search: key- |
| except=("x"), key-order | order, except=("x") |
+------------------------------+---------------------------+
| No-Vary-Search: params=() | (omit the header field) |
+------------------------------+---------------------------+
| No-Vary-Search: key-order=?0 | (omit the header field) |
+------------------------------+---------------------------+
Table 3
5.3. Parse a key
To _parse a key_ given an ASCII string _keyString_:
1. Let _keyBytes_ be the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode) [WHATWG-INFRA]
of _keyString_.
2. Replace any 0x2B (+) in _keyBytes_ with 0x20 (SP).
3. Let _keyBytesDecoded_ be the percent-decoding
(https://url.spec.whatwg.org/#percent-decode) [WHATWG-URL] of
_keyBytes_.
4. Let _keyStringDecoded_ be the UTF-8 decoding without BOM
(https://encoding.spec.whatwg.org/#utf-8-decode-without-bom)
[WHATWG-ENCODING] of _keyBytesDecoded_.
5. Return _keyStringDecoded_.
5.3.1. Examples
The parse a key algorithm allows encoding non-ASCII key strings in
the ASCII structured header field format, similar to how the
application/x-www-form-urlencoded
(https://url.spec.whatwg.org/#concept-urlencoded) format [WHATWG-URL]
allows encoding an entire entry list of keys and values in a URI
(which is restricted to ASCII characters). For example:
No-Vary-Search: params=("%C3%A9+%E6%B0%97")
Denicola, et al. Expires 13 February 2027 [Page 10]
Internet-Draft No-Vary-Search August 2026
Notice that while the input string "%C3%A9+%E6%B0%97" consists
entirely of ASCII characters (as required at the HTTP layer), the
percent-decoding step used by the cache produces a non-ASCII result.
This will result in a URL variation config whose no-vary params are «
"é 気" ». Note that the "+" character in the encoded string is mapped
to a space (SP). As explained in a later example, the
canonicalization process during equivalence testing means this will
treat as equivalent URIs such as:
* https://example.com/?é 気=1
* https://example.com/?é+気=2
* https://example.com/?%C3%A9%20気=3
* https://example.com/?%C3%A9+%E6%B0%97=4
and so on, since they all are parsed
(https://url.spec.whatwg.org/#concept-urlencoded-parser) [WHATWG-URL]
to having the same key "é 気".
6. Comparing
Two URLs (https://url.spec.whatwg.org/#concept-url) [WHATWG-URL]
_urlA_ and _urlB_ are _equivalent modulo variation config_ given a
URL variation config _variationConfig_ if the following algorithm
returns true:
1. If the scheme, host, port, or path of _urlA_ and _urlB_ differ,
then return false.
2. If _variationConfig_ is equivalent to the default URL variation
config, then:
1. If _urlA_'s query equals _urlB_'s query, then return true.
2. Return false.
In this case, even URL pairs that might appear the same after
running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] on their queries, such as https://example.com/a and
https://example.com/a?, or https://example.com/foo?a=b&&&c and
https://example.com/foo?a=b&c=, will be treated as inequivalent.
3. Let _searchParamsA_ and _searchParamsB_ be empty lists.
Denicola, et al. Expires 13 February 2027 [Page 11]
Internet-Draft No-Vary-Search August 2026
4. If _urlA_'s query is not null, then set _searchParamsA_ to the
result of running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] given the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode)
[WHATWG-INFRA] of _urlA_'s query.
5. If _urlB_'s query is not null, then set _searchParamsB_ to the
result of running the application/x-www-form-urlencoded parser
(https://url.spec.whatwg.org/#concept-urlencoded-parser)
[WHATWG-URL] given the isomorphic encoding
(https://infra.spec.whatwg.org/#isomorphic-encode)
[WHATWG-INFRA] of _urlB_'s query.
6. If _variationConfig_'s no-vary params is a list, then:
1. Set _searchParamsA_ to a list containing those items _pair_
in _searchParamsA_ where _variationConfig_'s no-vary params
does not contain _pair_[0].
2. Set _searchParamsB_ to a list containing those items _pair_
in _searchParamsB_ where _variationConfig_'s no-vary params
does not contain _pair_[0].
7. Otherwise, if _variationConfig_'s vary params is a list, then:
1. Set _searchParamsA_ to a list containing those items _pair_
in _searchParamsA_ where _variationConfig_'s vary params
contains _pair_[0].
2. Set _searchParamsB_ to a list containing those items _pair_
in _searchParamsB_ where _variationConfig_'s vary params
contains _pair_[0].
8. If _variationConfig_'s vary on key order is false, then:
1. Let _keyLessThan_ be an algorithm taking as inputs two pairs
(_keyA_, _valueA_) and (_keyB_, _valueB_), which returns
whether _keyA_ is code unit less than
(https://infra.spec.whatwg.org/#code-unit-less-than)
[WHATWG-INFRA] _keyB_.
2. Set _searchParamsA_ to the result of sorting
(https://infra.spec.whatwg.org/#list-sort-in-ascending-
order) [WHATWG-INFRA] _searchParamsA_ in ascending order
with _keyLessThan_.
Denicola, et al. Expires 13 February 2027 [Page 12]
Internet-Draft No-Vary-Search August 2026
3. Set _searchParamsB_ to the result of sorting
(https://infra.spec.whatwg.org/#list-sort-in-ascending-
order) [WHATWG-INFRA] _searchParamsB_ in ascending order
with _keyLessThan_.
9. If _searchParamsA_'s size is not equal to _searchParamsB_'s
size, then return false.
10. Let _i_ be 0.
11. While _i_ < _searchParamsA_'s size:
1. If _searchParamsA_[_i_][0] does not equal
_searchParamsB_[_i_][0], then return false.
2. If _searchParamsA_[_i_][1] does not equal
_searchParamsB_[_i_][1], then return false.
3. Set _i_ to _i_ + 1.
12. Return true.
6.1. Examples
Due to how the application/x-www-form-urlencoded parser canonicalizes
query strings, there are some cases where query strings which do not
appear obviously equivalent, will end up being treated as equivalent
after parsing.
So, for example, given any non-default value for the "No-Vary-Search"
response header field, such as No-Vary-Search: key-order, we will
have the following equivalences:
Denicola, et al. Expires 13 February 2027 [Page 13]
Internet-Draft No-Vary-Search August 2026
+=============+==============+============================+
| First Query | Second Query | Explanation |
+=============+==============+============================+
| null | ? | A null query is parsed the |
| | | same as an empty string |
+-------------+--------------+----------------------------+
| ?a=x | ?%61=%78 | Parsing performs percent- |
| | | decoding |
+-------------+--------------+----------------------------+
| ?a=é | ?a=%C3%A9 | Parsing performs percent- |
| | | decoding |
+-------------+--------------+----------------------------+
| ?a=%f6 | ?a=%ef%bf%bd | Both values are parsed as |
| | | U+FFFD (�) |
+-------------+--------------+----------------------------+
| ?a=x&&&& | ?a=x | Parsing splits on & and |
| | | discards empty strings |
+-------------+--------------+----------------------------+
| ?a= | ?a | Both parse as having an |
| | | empty string value for a |
+-------------+--------------+----------------------------+
| ?a=%20 | ?a= & | %20 is parsed as U+0020 |
| | | SPACE |
+-------------+--------------+----------------------------+
| ?a=+ | ?a= & | + is parsed as U+0020 |
| | | SPACE |
+-------------+--------------+----------------------------+
Table 4
Note that no Unicode normalization is performed during this
comparison. For example, a query string of ?a=%C3%A9 (using the NFC
encoding of é) and ?a=e%CC%81 (using the NFD encoding of é) will not
be treated as equivalent.
7. Caching
To reuse a stored response, Section 4 of [HTTP-CACHING] requires that
the presented target URI and that of the stored response match. If a
cache implements the No-Vary-Search extension, this matching
requirement is also satisfied if the URIs are equivalent modulo URL
variation config (Section 6) given the stored response's No-Vary-
Search header.
Denicola, et al. Expires 13 February 2027 [Page 14]
Internet-Draft No-Vary-Search August 2026
This document does not alter the requirements for cache invalidation
(see Section 4.4 of [HTTP-CACHING]). A cache MAY invalidate stored
responses for URIs that are equivalent modulo URL variation config,
but is not required to do so. Therefore, state-changing requests
might not invalidate all conceptually equivalent responses.
Note that the "No-Vary-Search" response header field operates in
addition to content negotiation and the Vary header field (see
Section 4.1 of [HTTP-CACHING]).
Cache implementations MAY fail to reuse a stored response whose
target URI matches _only_ modulo URL variation config, if the cache
has a stored response with a more recent Date header field which:
* has a target URI which is equal to the presented target URI,
excluding the query, and
* has a non-empty value for the "No-Vary-Search" response header
field, and
* has a "No-Vary-Search" response header field value different from
the stored response being considered for reuse.
When a cache has multiple stored responses with conflicting "No-Vary-
Search" values, preferring the response with the most recent Date
header field helps ensure caches converge on the origin's latest
caching policy.
| Caches aren't required to reuse stored responses, generally.
| However, the above expressly empowers caches to, if it is
| advantageous for performance or other reasons, search a smaller
| number of stored responses.
|
| That is, because caches might store more than one response for
| a given target URI path and authority, they need a way to
| efficiently look up the "No-Vary-Search" response header field
| value without accessing all cached responses. Such a cache
| might take steps like the following to identify a stored
| response in a performant way, before checking the other
| conditions in Section 4 of [HTTP-CACHING]:
|
| 1. Let exactMatch be cache[presentedTargetURI]. If it is a
| stored response that can be reused, return it.
|
| 2. Let targetPath be presentedTargetURI, with query
| parameters removed.
|
Denicola, et al. Expires 13 February 2027 [Page 15]
Internet-Draft No-Vary-Search August 2026
| 3. Let lastNVS be mostRecentNVS[targetPath]. If it does
| not exist, return null.
|
| 4. Let simplifiedURL be the result of simplifying
| presentedTargetURI according to lastNVS (by removing
| query parameters which are not significant, and sorting
| (https://infra.spec.whatwg.org/#list-sort-in-ascending-
| order) [WHATWG-INFRA] parameters in ascending order by
| key, if key order is to be ignored).
|
| 5. Let nvsMatch be cache[simplifiedURL]. If it does not
| exist, return null. (It is assumed that this was
| written when storing in the cache, in addition to the
| exact URL.)
|
| 6. Let variationConfig be obtained (Section 5.2) from
| nvsMatch.
|
| 7. If nvsMatch's target URI and presentedTargetURI are not
| equivalent modulo URL variation config (Section 6) given
| variationConfig, then return null.
|
| 8. If nvsMatch is a stored response that can be reused,
| return it. Otherwise, return null.
To aid cache implementation efficiency, servers SHOULD NOT send
different non-empty values for the "No-Vary-Search" response header
field in response to requests for a given target URI path and
authority over time, unless there is a need to update how they handle
the query component. Doing so would cause cache implementations that
use a strategy like the above to miss some stored responses that
could otherwise have been reused.
8. Security Considerations
The main risk to be aware of is a cache returning a response that was
originally fetched from a URL different from the one requested. In a
web browser, this could cause the user to see a response fetched from
a URL different from the one displayed when they hovered a link, or
the URL displayed in the URL bar.
Denicola, et al. Expires 13 February 2027 [Page 16]
Internet-Draft No-Vary-Search August 2026
For shared caches, such as CDNs or forward proxies, returning a
response for a different URL carries the risk of cross-user state
leakage. If a server incorrectly declares that a query parameter
does not affect the response, but that parameter actually dictates
user-specific or sensitive content, the shared cache might serve one
user's personalized response to another user. However, because the
origin strictly controls the "No-Vary-Search" response header field,
it is the origin's responsibility to ensure that ignored parameters
are safe to disregard for all users.
The "No-Vary-Search" response header field alters the algorithm that
caches use for URI identifier comparison. As discussed in [RFC6943],
altering identifier comparison logic can lead to security issues,
primarily through "false positives" where two identifiers are
incorrectly deemed equivalent.
Incorrect configuration of this field can exacerbate cache poisoning
or data leakage risks by causing such false positives. Origin
servers MUST NOT declare a parameter as no-vary if doing so would
bypass server processing required for safe response reuse. This
includes parameters used for authorization, user identification,
signature verification, user consent, routing, auditing, revocation,
or any other security-sensitive operations.
However, since the impact is limited to query parameters, this does
not cross the relevant security boundary, which is the origin
([ORIGIN]). (See also the host
(https://url.spec.whatwg.org/#concept-url-host) from the perspective
of web browser security UI (https://url.spec.whatwg.org/#url-
rendering-simplification) [WHATWG-URL]). Indeed, origins already
have complete control over how they present URLs and response bodies,
including on the client side via technology such as
history.replaceState() (https://html.spec.whatwg.org/multipage/nav-
history-apis.html#dom-history-replacestate) [HTML] or service
workers.
9. Privacy Considerations
This proposal is adjacent to the highly-privacy-relevant space of
navigational tracking (https://privacycg.github.io/nav-tracking-
mitigations/#terminology), which often uses query parameters to pass
along user identifiers. If an origin were to encode user identifiers
in its URI, this proposal can reduce user tracking by private caches,
since preventing server processing of such user IDs bypasses the
server in favor of the cache. It does not interfere with existing
navigational tracking mitigations (https://privacycg.github.io/nav-
tracking-mitigations/#deployed-mitigations), or any known future ones
being contemplated. [NAV-TRACKING-MITIGATIONS]
Denicola, et al. Expires 13 February 2027 [Page 17]
Internet-Draft No-Vary-Search August 2026
However, this tracking reduction does not fully apply to shared
caches (such as content delivery networks and forward proxies), which
still receive the requests containing the identifiers. Furthermore,
an errant configuration that incorrectly ignores parameters related
to user identity or private state could expose cached content meant
for one user to another. While this mistake can occur with standard
caching, the "No-Vary-Search" response header field increases the
surface area for such misconfigurations, making it critical that
origins accurately classify their query parameters.
10. IANA Considerations
10.1. HTTP Field Names
IANA is requested to enter the following into the Hypertext Transfer
Protocol (HTTP) Field Name Registry
(https://www.iana.org/assignments/http-fields/http-fields.xhtml
(https://www.iana.org/assignments/http-fields/http-fields.xhtml)):
Field Name: No-Vary-Search
Status: permanent
Structured Type: Dictionary
Reference: this document
Comments: (none)
10.2. No-Vary-Search Dictionary Keys Registry
IANA is requested to create a new registry, "No-Vary-Search
Dictionary Keys", at https://www.iana.org/assignments/http-fields/
(https://www.iana.org/assignments/http-fields/).
The registration policy is "IETF Review" (see Section 4.8 of
[RFC8126]).
A registration request MUST include the following fields:
* Key: the dictionary key for the "No-Vary-Search" response header
field
* Description: a brief description of the key's purpose
* Reference: a pointer to the specification that defines the key
The initial contents of this registry are:
Denicola, et al. Expires 13 February 2027 [Page 18]
Internet-Draft No-Vary-Search August 2026
+===========+==============================+===========+
| Key | Description | Reference |
+===========+==============================+===========+
| key-order | Indicates if query parameter | this |
| | order affects caching | document |
+-----------+------------------------------+-----------+
| params | A list of query parameters | this |
| | that do not affect caching | document |
+-----------+------------------------------+-----------+
| except | A list of query parameters | this |
| | that affect caching | document |
+-----------+------------------------------+-----------+
Table 5
11. References
11.1. Normative References
[HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Semantics", STD 97, RFC 9110,
DOI 10.17487/RFC9110, June 2022,
<https://www.rfc-editor.org/rfc/rfc9110>.
[HTTP-CACHING]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
Ed., "HTTP Caching", STD 98, RFC 9111,
DOI 10.17487/RFC9111, June 2022,
<https://www.rfc-editor.org/rfc/rfc9111>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
[STRUCTURED-FIELDS]
Nottingham, M. and P. Kamp, "Structured Field Values for
HTTP", RFC 9651, DOI 10.17487/RFC9651, September 2024,
<https://www.rfc-editor.org/rfc/rfc9651>.
[URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/rfc/rfc3986>.
Denicola, et al. Expires 13 February 2027 [Page 19]
Internet-Draft No-Vary-Search August 2026
[WHATWG-ENCODING]
van Kesteren, A., "Encoding Living Standard", n.d.,
<https://encoding.spec.whatwg.org/>. WHATWG
[WHATWG-INFRA]
van Kesteren, A. and D. Denicola, "Infra Living Standard",
n.d., <https://infra.spec.whatwg.org/>. WHATWG
[WHATWG-URL]
van Kesteren, A., "URL Living Standard", n.d.,
<https://url.spec.whatwg.org/>. WHATWG
11.2. Informative References
[HTML] van Kesteren, A., "HTML Living Standard", n.d.,
<https://html.spec.whatwg.org/>. WHATWG
[NAV-TRACKING-MITIGATIONS]
Snyder, P. and J. Yasskin, "Navigational-Tracking
Mitigations", n.d.,
<https://privacycg.github.io/nav-tracking-mitigations/>.
W3C Privacy CG
[ORIGIN] Barth, A., "The Web Origin Concept", RFC 6454,
DOI 10.17487/RFC6454, December 2011,
<https://www.rfc-editor.org/rfc/rfc6454>.
[RFC6943] Thaler, D., Ed., "Issues in Identifier Comparison for
Security Purposes", RFC 6943, DOI 10.17487/RFC6943, May
2013, <https://www.rfc-editor.org/rfc/rfc6943>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/rfc/rfc8126>.
Acknowledgments
This document benefited from valuable reviews and suggestions by:
* Adam Rice
* Julian Reschke
* Kevin McNee
* Liviu Tinta
Denicola, et al. Expires 13 February 2027 [Page 20]
Internet-Draft No-Vary-Search August 2026
* Mark Nottingham
* Martin Thomson
* Valentin Gosu
Index
D E O P
D
default URL variation config *_Section 4, Paragraph 3_*;
Section 5.1, Paragraph 2.1.1; Section 5.1, Paragraph
2.4.2.1.1; Section 5.1, Paragraph 2.5.1; Section 5.1,
Paragraph 2.7.2.1.1; Section 5.1, Paragraph 2.7.2.2.1;
Section 5.1, Paragraph 2.7.2.4.1; Section 5.1, Paragraph
2.8.2.1.1; Section 5.1, Paragraph 2.8.2.2.1; Section 5.1,
Paragraph 2.8.2.4.1; Section 5.1, Paragraph 3.1;
Section 5.2.1, Paragraph 3; Section 6, Paragraph 2.2.1
E
equivalent modulo variation config *_Section 6, Paragraph 1_*
O
obtain a URL variation config Section 4, Paragraph 4;
*_Section 5.2, Paragraph 1_*
P
parse a key Section 5.1, Paragraph 2.7.2.3.1; Section 5.1,
Paragraph 2.8.2.3.1; *_Section 5.3, Paragraph 1_*;
Section 5.3.1, Paragraph 1
parse a URL variation config *_Section 5.1, Paragraph 1_*;
Section 5.2, Paragraph 2.2.1
Authors' Addresses
Domenic Denicola
Google LLC
Email: d@domenic.me
Jeremy Roman
Google LLC
Email: jbroman@chromium.org
Denicola, et al. Expires 13 February 2027 [Page 21]
Internet-Draft No-Vary-Search August 2026
Nidhi Jaju (editor)
Google LLC
Email: nidhijaju@chromium.org
Denicola, et al. Expires 13 February 2027 [Page 22]