ETag
An ETag (entity tag) is an HTTP response header that identifies a
specific version of a resource — typically a hash of its content. It lets browsers and
CDNs ask "has this changed?" instead of re-downloading the whole thing: the client sends
the ETag back in an If-None-Match request header, and if the version still
matches, the server answers 304 Not Modified with an empty body.
How ETag revalidation works
The first response carries the tag:
HTTP/2 200
etag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
cache-control: max-age=3600
Once the cached copy's TTL expires, the client revalidates instead of refetching:
GET /style.css
if-none-match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
HTTP/2 304 Not Modified
A 304 costs one round trip but no body transfer — for a large asset that's the difference between milliseconds and a full re-download. CDNs use the same mechanism upstream: an edge server revalidates its stale copy against your origin and refreshes the entry's freshness without moving bytes.
Strong vs. weak ETags
A strong ETag ("abc123") promises byte-for-byte identity. A weak ETag
(W/"abc123") promises only semantic equivalence — the content is
"the same enough" (say, a timestamp in a footer changed). Weak ETags can't be used for
byte-range requests, but both work for revalidation.
The pitfalls worth knowing
- Multi-server setups: Apache's default ETag once included inode numbers, so identical files on different servers produced different tags — breaking revalidation behind load balancers. Derive ETags from content only.
- Compression changes bytes: some servers emit different ETags for
gzip, Brotli and identity variants of the same resource (or append
-gzipsuffixes). Combined with Vary: Accept-Encoding this is correct behavior, but it surprises people diffing headers. Check what your stack sends with our compression test. - ETag ≠ caching policy: an ETag alone doesn't make a response cacheable — it only enables revalidation. Freshness still comes from Cache-Control.
ETags and CDN caching
Revalidation makes expiry cheap, but the visitor still waits for the origin round trip whenever the edge copy has expired. That's why a healthy setup combines sensible ETags with a long s-maxage — and re-warms edge caches after purges, so real visitors hit fresh copies instead of triggering revalidations. See our cache hit ratio guide for where revalidation fits into the bigger picture.