TATECHATLAS
◎ English
Web & APIs

ETag and Conditional Requests: Revalidation and Safe Updates

Use If-None-Match to revalidate cached responses and If-Match to avoid overwriting a newer representation.

On this page

ETag is a validator identifying a particular representation of a resource. A client can return the received tag in If-None-Match when reading, or in If-Match when updating. A matching If-None-Match on GET or HEAD can produce 304 Not Modified, allowing reuse of the stored response body. A failed If-Match precondition produces 412 Precondition Failed, so the client can reload the changed resource before editing again. These mechanisms solve different problems. Neither an ETag nor a successful conditional request grants access or proves that cached content may be shared with other users.

Understand what an ETag identifies

An ETag belongs to a selected representation, not merely to its URL. The server chooses its value and the client treats it as an opaque identifier. A tag need not be a file hash, timestamp or revision number. If the response varies by language or other request headers, the selected representation matters. Before implementing validation, identify which response was stored, which request selected it, and which tag arrived with that response.

Keep tags opaque and correctly quoted

Preserve the received tag exactly, including quotes and a possible W/ prefix. The illustrative response uses ETag: "version-a". A client should not remove quotes, reconstruct the value from a local clock, or infer ordering from the name. The server may use another scheme entirely. Store the validator together with the corresponding response, rather than keeping one global tag for every resource or combining a tag from one language with another language's body.

HTTP/1.1 200 OK
ETag: "version-a"
Cache-Control: private, no-cache
Content-Type: application/json

{"title": "Example"}

Revalidate with If-None-Match

When a stored response needs validation, send its tag in If-None-Match on a GET request. If the selected representation still matches, the server can return 304; otherwise it returns the requested representation normally, commonly with 200 and a new validator. Revalidation reduces repeated body transfer, but still involves a request to the server. A fresh reusable cached response can instead be served without that validation request, depending on the cache policy.

GET /documents/42 HTTP/1.1
Host: example.com
If-None-Match: "version-a"

Handle 304 without losing the saved body

A 304 response has no representation body to replace the saved content. Keep the previously stored body and update the relevant cache metadata according to the response headers. Do not overwrite your stored document with an empty string simply because the network response has no body. If your application lacks the corresponding stored representation, it cannot reconstruct the resource from 304 alone. Make a suitable request to obtain the body and rebuild a consistent cache entry.

HTTP/1.1 304 Not Modified
ETag: "version-a"
Cache-Control: private, no-cache

Protect edits with If-Match

For an update, send the validator of the representation the user actually edited in If-Match. If another writer has changed it, the precondition can fail with 412. Reload the current representation and ask the user to reconcile the changes instead of blindly repeating the same write. The server must correctly enforce the precondition together with its update operation; merely displaying an ETag in the interface does not prevent a lost update.

PUT /documents/42 HTTP/1.1
Host: example.com
If-Match: "version-a"
Content-Type: application/json
Content-Length: 21

{"title": "Updated!"}

Distinguish strong and weak validators

A strong validator represents byte-level equivalence; a weak tag, marked W/, permits weaker equivalence. If-None-Match uses weak comparison, which is useful for cache revalidation. If-Match uses strong comparison, so a weak tag does not provide a matching strong validator for an edit. Avoid manually deleting W/ to manufacture a strong tag. If the service only supplies weak validators, use an update mechanism it actually supports rather than assuming every ETag is interchangeable.

Combine validators with cache policy

ETag does not replace Cache-Control or Vary. Cache-Control governs caching behavior; Vary identifies request headers that affect representation selection. In particular, no-cache means a stored response needs validation before reuse, while no-store prohibits storing the response. Content for an authenticated user also needs an appropriate policy for private or shared caches. Work out who may store each representation and when it may be reused before adding validators to an otherwise unspecified cache.

Diagnose conditional requests step by step

Inspect the first response's status, ETag, Cache-Control and Vary. Then compare a conditional read with an unchanged resource and with a changed representation. For edit conflicts, inspect the tag sent in If-Match and the returned status. Log resource identifiers and statuses rather than sensitive bodies. The HTTP blocks are illustrative exchanges, not an executed network test. This small sequence helps distinguish an absent saved body, an incorrect validator and a server that ignores preconditions.

Things to check

  • Keep each received ETag with the exact representation it validates.
  • Reuse a stored body on 304; do not replace it with an empty network body.
  • Handle 412 as an edit conflict and reload before retrying.
  • Check Cache-Control, Vary and the strong or weak validator type together.

Conditional requests require correct client storage and server enforcement. They do not provide authorization, confidentiality or a complete application-level conflict resolution policy. The examples describe HTTP semantics and do not claim measured bandwidth savings.

Sources

  1. MDN: HTTP conditional requests ↗
  2. MDN: ETag ↗
  3. RFC 9110: HTTP semantics and conditional requests ↗
  4. RFC 9111: HTTP caching ↗
Back to top ↑