HTTP cache validation 2026-11-05
HTTP cache validation checks whether a stored HTTP response remains suitable for reuse, commonly by sending an HTTP conditional request containing a validator such as an entity tag. It supports reusing stored representation data while checking with a server whether the relevant state has changed.[ref]
Validation and HTTP freshness answer different questions. A stored response may still be fresh according to its lifetime and age, allowing reuse under the applicable rules without this exchange. A response that is no longer fresh is not thereby known to have different content at the origin: validation can establish that reuse remains appropriate.[ref]
Suppose a cache stores a successful
/manual response with a -octet body and entity tag "manual-4". Assume that it is otherwise eligible for reuse after successful validation. A later GET sends If-None-Match: "manual-4". If the selected HTTP representation still matches, the origin returns 304 without a representation body. The cache identifies the matching stored response, updates its fields according to the validation rules, and reuses its stored data.[ref][ref]In that unchanged branch, the origin avoids retransmitting the representation-body octets. The validation request and response still have a cost; the body count alone is not a measurement of total network savings. Nor is
304 an empty replacement document: the useful data are the body already held by the cache.If the selected representation changed, an otherwise successful validation request can instead receive a full response with its new data. The cache uses that response to satisfy the request and may store it subject to the ordinary storage constraints.[ref] A validator alone does not make every stored response reusable: selection inputs, applicable cache controls and the result of validation still matter.
The comparison rule also matters.
If-None-Match uses weak entity tag comparison, so HTTP cache validation can accept the server's declared equivalence through a weak entity tag. An update requiring an exact precondition through If-Match instead uses strong entity tag comparison.[ref] HTTP conditional request 2026-11-05
An HTTP conditional request carries one or more preconditions to be evaluated before applying its HTTP request method. The condition can ask whether the selected HTTP representation still has a previously observed entity tag. This makes the request depend on the state the client knows, rather than applying an operation unconditionally.[ref]
For HTTP cache validation, suppose an earlier retrieval of
/color stored the text blue with entity tag "v7". A later GET with If-None-Match: "v7" asks for the representation only if its tag no longer matches. If the selected representation still matches, the condition is false and the server returns status 304 instead of transferring the representation data again. If it has changed, an otherwise successful retrieval can return the new data.[ref]A second use prevents overwriting another client's work. Suppose two clients read version
"v7". The first makes an update and the server assigns version "v8". The second submits a different PUT with If-Match: "v7". The stale tag does not match, so the server must not apply that update; in this example it returns 412. Checking and applying the condition as part of the operation prevents the second client from silently replacing the first client's changes.[ref]The two field names deliberately use different comparisons:
If-Match requires strong entity tag comparison, while If-None-Match uses weak comparison and can match a weak entity tag. Failed If-Match need not always yield 412: the specification permits a success response when the requested change appears already applied. Authentication, redirects and other normal request checks also precede precondition evaluation. An HTTP conditional request therefore combines method semantics, a particular condition and the specified evaluation order. HTTP current age 2026-11-05
HTTP current age is a cache's estimate of an HTTP response's age at the time it is considered for reuse. It includes age accumulated before the response reached this cache and the time it has since spent there. The received
Age field is therefore an input to the calculation, not generally the response's current age at every later instant.[ref]Write for the request time, for response receipt, for now, for the
Date value and for the received Age value, all in compatible seconds. The RFC defines HTTP apparent age and HTTP response delay throughIt permits as the corrected initial age. For paths with very old caches, it also gives the more conservative choiceThe current age then adds local residence:The maximum-based choice is an allowed conservative alternative, not the only permitted initial-age calculation.[ref]HTTP Caching. §4.2.3, apparent_age, response_delay, corrected_age_value and corrected_initial_age alternatives
For an own clock example, set , , , and . Assume adequately synchronized clocks and use the conservative choice. Apparent age is , response delay is , and corrected age is . ThusUsing only local residence would have produced six seconds and substantially understated the estimated age.
If the HTTP freshness lifetime is seconds, this response is fresh at the example's current time because . At , its age reaches and that strict comparison fails. HTTP freshness still does not replace the other rules governing cache reuse or HTTP cache validation.
The calculation combines local intervals with metadata supplied by other machines. The apparent-age route assumes reasonable clock synchronization, while the delay-corrected route accounts for time spent obtaining the response. Treating
Date or Age as a simple local stopwatch reading would lose those distinctions.[ref] HTTP freshness 2026-11-05
HTTP freshness describes whether a stored HTTP response is young enough for reuse according to its applicable lifetime. The comparison isThe strict inequality matters: a response exactly at its lifetime boundary is no longer fresh.[ref]
The HTTP freshness lifetime can come from explicit cache controls or, where permitted, a heuristic. The HTTP current age accounts for age accumulated before the response entered the present cache as well as its residence there. Counting only the seconds since this cache received the response can therefore underestimate its age.[ref]
For an own example, suppose the applicable lifetime is seconds and the correctly calculated current age at a chosen instant is seconds. Keep the lifetime fixed. After another seconds, the age is , so and the response remains fresh. After another seconds from the original instant, the age is and the strict comparison fails. After seconds it is , again stale. These calculations start from a given current age; they do not derive it from local residence time alone.
Freshness and HTTP cache validation answer different questions. An old response might still match the origin's present HTTP representation. Validation can establish that reuse remains appropriate without retransmitting the representation body. Conversely, a fresh response has not thereby been checked against the origin at every use.[ref]
Other rules still govern reuse. For example, the unqualified
Cache-Control: no-cache response directive requires successful validation before subsequent use, even though the response can be stored. Stale-serving rules also have explicit conditions. A freshness calculation is therefore one part of deciding whether a stored HTTP response may satisfy a particular request, rather than a complete permission test.[ref] HTTP heuristic freshness 2026-11-05
HTTP heuristic freshness estimates an HTTP freshness lifetime when a stored HTTP response lacks explicit expiration information and is otherwise eligible for that treatment. It allows constrained reuse when the origin has not supplied a lifetime, without pretending that the origin explicitly guaranteed one.[ref]
Eligibility comes first. The RFC permits heuristics for otherwise allowed responses that are heuristically cacheable by status or explicitly marked cacheable, when explicit freshness information is absent. A cache must not replace an explicit expiration time with its own heuristic. The ordinary storage constraints still apply.[ref]
HTTP Caching. §4.2.2, permitted responses and prohibition when explicit expiration is present; §3, storage constraints
For an own example, assume a successful response satisfies those conditions and has no restrictive directives. Its
Date corresponds to time seconds and Last-Modified to seconds. Choose a cache policy that fixes its lifetime at one tenth of the interval between those timestamps:At HTTP current age seconds, and fifteen seconds remain until the freshness boundary. At age , the strict comparison fails.The fraction and exact timestamp policy are stated assumptions of this example. The RFC encourages a fraction of the interval since modification and mentions ten percent as a typical setting, but does not prescribe a universal heuristic algorithm or require that fraction.[ref]
A long time since modification is evidence useful to an estimate; it is not proof that the origin will remain unchanged for the chosen lifetime. HTTP cache validation can later check whether a stored representation remains suitable. Different permitted heuristics can also produce different lifetimes from the same metadata.
An HTTP private cache and an HTTP shared cache must each respect the applicable caching constraints; being private or shared does not authorize arbitrary estimation. When an origin needs explicit freshness behavior, an explicit control such as
max-age avoids relying on the cache to infer that lifetime.[ref] HTTP private cache 2026-11-05
An HTTP private cache is dedicated to a single user. It is often implemented as part of a user agent, but its defining property is the single-user scope rather than a particular machine or storage medium. An HTTP shared cache can instead reuse responses for multiple users.[ref]
HTTP Caching. §1, cache definitions
Suppose a user's response carries
Cache-Control: private, max-age=60. The unqualified private directive permits a private cache to store the response subject to the normal storage rules, while forbidding a shared cache from storing it. The max-age directive supplies its explicit HTTP freshness lifetime; it does not cancel the single-user storage restriction.[ref]If the correctly calculated HTTP current age is twenty seconds, sixty seconds exceeds that age and forty seconds remain until the freshness boundary. Reuse still requires matching the relevant request and satisfying other applicable constraints. At current age sixty, the strict freshness comparison fails; HTTP cache validation may then establish whether the stored representation remains suitable.[ref]
Being private does not mean that every response must be stored or may be reused indefinitely. A cache can discard an entry, and an otherwise applicable restrictive directive remains significant. In particular, unqualified
no-cache requires successful validation before subsequent reuse, whereas no-store prohibits the corresponding storage and reuse under its defined rules.[ref]The word private is also a cache-control distinction, not an encryption mechanism or a promise that the message is inaccessible to everyone else. The standard explicitly separates those meanings. Correct HTTP cache key selection and response handling still matter inside a single-user cache.[ref]
HTTP shared cache 2026-11-05
Weak entity tag 2026-11-05
A weak entity tag is an entity tag explicitly marked
W/ whose validation guarantee does not require distinguishing every change to the HTTP representation data. A server may group representations it regards as suitable substitutes, rather than identify each distinct sequence of bytes. The weak marker is case-sensitive.[ref]For an invented example, an HTML resource sometimes ends its source with an extra newline. Stipulate that this does not change its relevant rendered meaning and that the server considers both forms interchangeable for reuse. It can retain
W/"page-4" across those two forms. It should change the tag when it no longer regards an older representation as an acceptable substitute. This policy is a server decision, not a license for clients to ignore arbitrary differences.[ref]Weak comparison ignores whether a tag is marked weak but still compares the opaque value character for character. Consequently
W/"page-4" weakly matches both W/"page-4" and "page-4"; it does not match W/"Page-4". Strong comparison fails whenever either operand is a weak entity tag, even when their opaque values agree.[ref]This distinction supports HTTP cache validation. An HTTP conditional request with
If-None-Match: W/"page-4" uses weak comparison, so a matching selected representation can produce 304 for GET. An update protected by If-Match instead requires a strong entity tag comparison and cannot obtain that guarantee from this weak tag.[ref]