October 12, 2026 · 3 min read · Yunus Emre Vurgun

HTTP Caching with ETags and Cache-Control

http · caching · api · reference
In this guide
  1. A complete request sequence
  2. Choose a policy by the content
  3. Verify the failure paths
  4. Reference tables to keep nearby
  5. Primary sources

A cache needs two separate decisions: whether it may reuse a response now, and how to check the response after it becomes stale. Cache-Control answers the first question. Validators such as ETag help answer the second. Mixing those jobs produces either needless downloads or unexpectedly old data.

Consider a public dictionary downloaded by many clients. A five-minute freshness window is acceptable, but sending the entire file every five minutes is wasteful. Give the representation a validator that changes when its content changes, and make the cache policy explicit. Do not use a personalized response for this example: shared caching requires a separate privacy decision.

A complete request sequence

GET /dictionary.json HTTP/1.1

HTTP/1.1 200 OK
Cache-Control: public, max-age=300
ETag: "dictionary-7"
Content-Type: application/json

During freshness, a cache may reuse the response without asking the origin. After that interval, the client sends If-None-Match: "dictionary-7". If the selected representation still matches, the server responds with 304 and cache metadata. The client keeps its stored body. If the representation changed, the server returns the new body with a new validator.

Handle 304 before trying to parse a response as JSON. There is no replacement representation body to parse. A small command-line client that persists its own cache must also retain the previous body and apply response metadata correctly; a conditional request alone does not create a cache.

Choose a policy by the content

For a hashed stylesheet, a long freshness lifetime with immutable is appropriate when a content change also changes the URL. For an editable public reference file, choose a bounded lifetime or require validation. For a user-specific response, consider private or no-store according to the actual storage requirements. No-cache permits storage but requires validation before reuse; it is not a synonym for no-store.

Test both the origin and any CDN. A CDN can add age, vary cache keys, or impose its own configuration. Record the response headers from the first request, a fresh reuse, and a stale validation. That three-step trace is more useful than checking only that one header exists.

Verify the failure paths

  • Change the body and confirm the validator changes.
  • Check negotiated variants so one representation does not reuse another’s validator incorrectly.
  • Confirm authenticated content never enters an unintended shared cache.
  • Test a 304 with an existing cached body and a client with no cached body.

Reference tables to keep nearby

Primary sources

These are the specifications and project documentation behind the examples. Check the relevant implementation and version before applying a pattern.

Reference data for this guide

Search the library

Search by a topic, title, or keyword.

Start with a collection

Browse all 205 datasets