ETag and Conditional Requests

ETags let a client identify a particular representation of a resource and ask the server whether that representation is still current. A conditional request can therefore avoid retransferring an unchanged response body.

An ETag is a response header containing an opaque identifier for a specific representation of a resource. A client can store the ETag alongside its cached response and later send it in `If-None-Match` when requesting the resource again.

If the server determines that the requested representation still matches the supplied validator, it can return `304 Not Modified` without a response body. The browser can then reuse its cached representation, reducing transferred bytes and often improving perceived performance.

If the representation has changed, the server normally returns the new representation, commonly with `200 OK`, and supplies a new ETag. The cache can replace its previous copy and validator with the new response.

ETags are validators, not cache lifetimes. Cache-control directives such as `max-age` determine when a cached response can generally be reused without contacting the server, while conditional requests provide a way to revalidate a cached response with comparatively little data transfer.

ETags can be strong or weak. A strong ETag is intended to identify an equivalent representation for byte-for-byte reuse, while a weak ETag, prefixed with `W/`, permits the server to indicate semantic equivalence even when representations are not byte-identical.

Key points

Interview questions

What problem does an ETag solve?

An ETag gives a cached representation an identifier that the client can later use for validation. The client sends that identifier in `If-None-Match` on a subsequent request. If the server says the representation has not changed, it can return `304 Not Modified` instead of sending the body again. This saves bandwidth while still allowing the client to verify freshness with the server.

Walk me through a conditional GET using ETag.

First, the server returns a representation with an `ETag`, and the browser stores both the response and validator in its cache. Later, when the cached response needs validation, the browser sends `If-None-Match` containing the stored ETag. If the representation still matches, the server returns `304 Not Modified`, allowing the browser to reuse its cached body. If it does not match, the server sends the current representation, typically with a new ETag.

What is the difference between strong and weak ETags?

A strong ETag is intended to identify a representation precisely enough for strong comparison, including byte-level equivalence. A weak ETag begins with `W/` and indicates that the server considers representations semantically equivalent for the relevant cache-validation purpose even if their bytes differ. Weak validators therefore should not be treated as interchangeable with strong validators in operations requiring exact representation identity.

How do ETag and Cache-Control work together?

They address different parts of caching. `Cache-Control` can tell a cache how long a response remains fresh and whether it should revalidate before reuse. Once validation is needed, an ETag can let the client send `If-None-Match` so the server can confirm that the cached representation remains valid without retransmitting the body. Thus, ETag is primarily a validator, while cache-control directives govern freshness and reuse.

Why might an application use ETags even when bandwidth is not its main concern?

Conditional requests can reduce the amount of representation data transferred during revalidation, which can lower latency and network utilization. They also provide a standardized mechanism for determining whether a cached representation remains current. Beyond browser caching, validators can be useful when representations are expensive to transfer or generate. The exact benefit depends on cache policy, representation size, server cost, and network conditions.