HTTP

HTTP Caches: Freshness, Validators and Variants

Choose an explicit response policy and distinguish a fresh cache hit from conditional reuse of an existing representation.

On this page
  1. Freshness and validation are different decisions
  2. Choose directives for the intended reader
  3. Make variants part of the fixture
  4. Distinguish internal and HTTP caches
  5. Plan invalidation at the correct layer
  6. References and related notes

A fast second request can have several explanations. A browser may reuse a fresh response, validate an older representation or reach an application that has its own internal cache. Those outcomes move different amounts of work and data. A useful cache review names the layer and the decision being examined instead of reporting every quick response as a cache hit.

Start with one resource and one intended policy. State whether its response is public, specific to a visitor or sensitive enough that storage should be prohibited. Then identify the browser, shared edge and application caches that might participate. The same request can encounter more than one independent lifetime.

Freshness and validation are different decisions

A fresh stored response can satisfy an eligible request without fetching the representation again. A stale response can sometimes be reused after a successful validation. An ETag is a validator attached to a representation; a conditional GET can send it in If-None-Match so the origin can decide whether that stored representation is still applicable.

In an illustrative exchange, the first response supplies a body and a validator. A later conditional request produces 304 Not Modified. The 304 does not carry a replacement page body; the client uses its stored representation with the applicable updated metadata. A client without that stored body cannot treat an isolated 304 as a complete page.

HTTP/1.1 200 OK
Cache-Control: public, max-age=60
ETag: "note-revision-7"
Content-Type: text/plain

An illustrative public note.
GET /note.txt HTTP/1.1
Host: example.com
If-None-Match: "note-revision-7"

These fragments describe a fixture design. They are not captured Nedan headers and do not assert that its routes use this policy. A real test must include the actual response metadata and the cache layer responsible for interpreting it.

Choose directives for the intended reader

The unqualified no-cache directive requires validation before reuse; it does not simply prohibit storage. No-store prohibits storage of the relevant exchange. Private constrains shared-cache storage. These differences matter when writing a policy for a public article, an account page or a response containing credentials.

Attach the policy to the representation's actual sensitivity and variation. Do not make a personalized response public merely because an edge cache improves latency. Check what the selected cache does with authorization and cookies rather than assuming a header name alone makes every implementation safe.

For a public versioned asset, a longer explicit lifetime can be suitable when its URL changes with the content. For an editable note at a stable URL, choose a lifetime consistent with the acceptable delay before readers see an update. Those are product decisions that should appear in the release review, not hidden defaults discovered during an incident.

Make variants part of the fixture

Vary identifies request fields that affect selection of a stored response. If two legitimate requests produce different representations, the cache policy and key must preserve that distinction. Test the specific variant fields used by the application. Avoid describing a cache as correct after checking only one convenient language or content encoding.

Keep the fixture small: two requests that should share a public representation, and two that must remain separate. Record which header or other rule creates the separation. Include a deliberately repeated request to each variant so the test examines reuse as well as the initial response.

An ETag is not an authenticity signature or a substitute for TLS. Treat it as an origin-defined validator whose meaning depends on the representation and comparison rules. A weak validator and a strong validator have different semantics; do not infer byte identity or security guarantees from the mere presence of the field.

Distinguish internal and HTTP caches

An application can cache an external API result internally while returning newly rendered HTML to every visitor. That internal lifetime is a different contract from the browser's response policy. A fresh application cache can reduce upstream traffic even when the public response itself is not stored by a shared HTTP cache.

Nedan's engineering feed uses that separation: local publication pages can remain useful when the optional metadata source fails. To review such a design, record upstream refresh frequency, failure backoff and what the public status says about the data. Do not call an application cache timestamp proof of a browser or proxy cache hit.

The fixture should include a successful refresh, repeated reads and an upstream failure. Compare the permitted upstream request count with the intended cache behavior. Keep the result narrow: a controlled sequence verifies those cases, not every later refresh or production traffic pattern.

Plan invalidation at the correct layer

Purging an edge does not remove copies already stored in browsers. Changing a server header does not rewrite all earlier responses. Before a release, decide whether a changed URL, validation or waiting for an existing lifetime is the intended transition mechanism. Record which layers the action actually controls.

For the review report, include the resource, response policy, initial representation, conditional exchange and expected variant behavior. Separate observed network transfers from a tool's presentation of a cached result. Browser tools and command-line probes can show different views because they have different storage state.

A good conclusion is specific: this public fixture reused the expected representation after validation, while these two variants remained distinct. The next unanswered question might concern a shared edge or a personalized response. State that question directly rather than extending one successful fixture into a claim about all HTTP caching.

Primary sources: RFC 9111, HTTP semantics in RFC 9110, MDN's cache guide and ETag reference. Examples and review procedures above are original explanatory fixtures.

Connect the cache observations to the request map and the timing notebook.