HTTP cache key 2026-11-05
An HTTP cache key is the information an HTTP cache uses to choose a stored response. The standard's minimum basis comprises the request method and target URI, while additional request information can distinguish negotiated responses or partition storage. Common caches that store only GET responses can use the URI alone for that minimum basis.[ref]
For an own example, suppose a cache holds both JSON and HTML responses for GET /report, each with Vary: Accept. Their explanatory selection inputs are (GET, /report, Accept=application/json) and (GET, /report, Accept=text/html). The target and method agree, but the nominated field distinguishes the variants. Another matching request for JSON must not receive the HTML entry merely because its target is also /report.[ref]
A request for /report?page=2 also has a different target from /report. Sharing a path prefix is not enough to identify a stored response. The example's tuples describe selection information rather than prescribe a particular serialized key or database implementation.
Field matching itself follows the specification. It can include the normalization permitted for the nominated fields; comparing every raw header string byte for byte is not the general rule. A missing field and an arbitrary different value also cannot be silently treated as equivalent.[ref]
Selection and permission to reuse are separate steps. A matching stored response must still satisfy the applicable cache controls and HTTP freshness or validation requirements. An HTTP private cache and an HTTP shared cache differ in their scope and some controls, but neither can infer complete reuse permission from a key match alone.[ref]
The key becomes especially important with HTTP content negotiation: several representations can belong to one resource without being interchangeable for every request. Identifying the selection dimensions explains both correct reuse and why one broadly shared target identifier need not yield one universal cached body.
HTTP freshness lifetime 2026-11-05
The HTTP freshness lifetime is the duration against which an HTTP response's HTTP current age is compared to determine HTTP freshness. It can be specified explicitly or, where allowed, estimated by a cache. It is not the same as the amount of fresh time remaining: that depends on the response's current age as well.[ref]
For valid explicit metadata, the RFC applies the first relevant rule. An HTTP shared cache uses s-maxage when present; otherwise max-age applies. If neither applicable directive is present, Expires supplies an expiration time from which the response's Date is subtracted, with the specified receipt-time fallback when Date is absent. Only when there is no explicit expiration time can HTTP heuristic freshness be applicable.[ref]
Consider a response with Cache-Control: max-age=600, s-maxage=60. An HTTP shared cache, which serves more than one user, takes a -second lifetime. An HTTP private cache, dedicated to one user, uses seconds instead. Assume the response otherwise satisfies the relevant storage and reuse rules.[ref]
At current age seconds, the shared cache has seconds until its freshness boundary, while the private cache has . At age , the shared response is no longer fresh because is false; the private cache's comparison still succeeds. These are two cache policies for the same response metadata, not conflicting estimates of the response's age.
HTTP heuristic freshness is constrained estimation, not an instruction to assign every response an arbitrary lifetime. The RFC allows heuristics under specified conditions and does not prescribe one universal estimation algorithm.[ref]
Finally, a computed lifetime does not override every other directive. Conflicting controls require the restrictive handling specified by the RFC; a freshness calculation also does not force a user agent to refresh its visible page. The lifetime governs cache operation, while the complete reuse decision still depends on the request and applicable response rules.[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]
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]
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]
For negotiated content, the stored representation can depend on request fields as well as the target. A private cache must therefore apply the same relevant matching rules rather than treating every request by its one user as interchangeable.
HTTP shared cache 2026-11-05
An HTTP shared cache stores HTTP responses for reuse by more than one user. It is often part of an intermediary, though that deployment is not required by the definition. An HTTP private cache is instead dedicated to a single user.[ref]
For an own example, suppose four users request the same public manual through one shared cache. The first request obtains a complete, cacheable response with a -octet body. Assume the following three requests match the required HTTP cache key inputs, arrive while the stored response remains reusable, and have no directives requiring forwarding. They can be satisfied from that stored response. The origin then sends the body once instead of four times, avoiding origin-body octets in this stipulated sequence. This does not count headers, validation traffic or delivery from the cache to the users.
Matching the target identifier alone need not be sufficient. If the response uses Vary: Accept, the relevant request-field matching rules also matter; one user's negotiated HTTP representation is not automatically suitable for another request's preferences.[ref] HTTP content negotiation and cache selection therefore interact.
Storage and reuse are separate decisions. The unqualified Cache-Control: private response directive forbids storage by a shared cache. Other responses must still satisfy the ordinary storage constraints, and the cache must consider HTTP freshness or successful HTTP cache validation when constructing a later response.[ref]
A shared cache also interprets s-maxage when present. For Cache-Control: max-age=600, s-maxage=60, its explicit freshness lifetime is sixty seconds rather than six hundred. This gives the origin a way to specify a shared reuse interval independently of the corresponding private-cache interval.[ref]
The benefit comes from reusing an eligible response across users, not from assuming all users receive identical content. State selection inputs and cache controls before extrapolating the simple manual example to personalized or negotiated resources.