ETag vs Last-Modified: Which Validator to Use

Choosing a validator is not cosmetic — it determines how precisely a cache can detect that a resource changed, how much CPU the origin spends answering revalidation requests, and what happens when both validators disagree. This guide walks through the decision with a comparison table and a decision flow, then shows how to confirm in practice which validator your server actually honors.

Prerequisite Concepts

Step-by-Step Resolution

Step 1 — Compare the two validators directly

Dimension ETag Last-Modified
Precision Arbitrary — a content hash or version tag distinguishes any two distinct byte sequences Capped at 1-second resolution (HTTP-date format has no sub-second component)
Compute cost Higher if hashed per request; near-zero if precomputed at build/deploy time Low — a single filesystem stat call, no body read required
Multi-server consistency High, if derived from content or an application version column Low, if derived from filesystem mtime that differs across cluster nodes
CDN / proxy handling Forwarded verbatim unless the edge transforms the body (compression, minification) Forwarded verbatim; largely immune to compression side effects since it’s a timestamp, not a body-derived value
Client conditional header If-None-Match / If-Match If-Modified-Since / If-Unmodified-Since
Range request support Only with a strong validator (see Strong vs Weak ETags Explained) Not used for range validation at all — ranges rely on ETag/If-Range in practice
RFC precedence when both present Wins — RFC 9110 §13.2.2 Ignored if If-None-Match is also sent

Step 2 — Apply the decision flow

ETag vs Last-Modified Decision Flow A decision flowchart: if sub-second precision or clustered origin consistency matters, use ETag with a content hash; otherwise Last-Modified alone may suffice; when both are present, ETag always takes precedence per RFC 9110. Resource needs a validator Sub-second precision or clustered origin needed? Yes Use ETag (content hash) No Compute cost of hashing is negligible? Yes Emit both ETag + Last-Modified No Last-Modified alone is sufficient cheap stat-based validation If both end up present: ETag always wins (RFC 9110 §13.2.2)

In plain terms: reach for a content-hash ETag whenever precision matters or your origin runs on more than one node. Fall back to Last-Modified alone only for cheap, single-node, coarse-grained resources where a filesystem timestamp is good enough. When in doubt, emitting both costs little and maximizes compatibility.

Step 3 — Confirm the RFC 9110 precedence rule empirically

Capture both validators from a live resource:

curl -sI https://example.com/report.pdf | grep -iE 'etag|last-modified'
ETag: "b7c92f1e004a"
Last-Modified: Sun, 05 Jul 2026 18:00:00 GMT

Now send a request with a stale If-Modified-Since (a date before the resource last changed, which alone would force a 200 OK) but a matching If-None-Match:

curl -sI \
  -H 'If-Modified-Since: Mon, 01 Jan 2024 00:00:00 GMT' \
  -H 'If-None-Match: "b7c92f1e004a"' \
  https://example.com/report.pdf

Expected result:

HTTP/1.1 304 Not Modified

The 304 proves the server evaluated If-None-Match and ignored the older, technically-failing If-Modified-Since — exactly the precedence RFC 9110 §13.2.2 mandates. If your server instead returns 200 OK here, it is not correctly prioritizing ETag, and you should treat Last-Modified on that platform as unreliable for combined use.

Step 4 — Verify CDN-level validator behavior

Different CDNs revalidate against different validators when their own edge TTL lapses. Check via response headers through the CDN versus direct to origin:

curl -sI https://example.com/report.pdf | grep -iE 'etag|last-modified|cf-cache-status|x-cache|age'

If the CDN dashboard or debug headers show revalidation requests reaching your origin with If-None-Match set, the edge is using ETag. Some CDNs default to whichever validator is present and prefer ETag when both exist, matching the RFC 9110 precedence rule; confirm the specific behavior for your provider rather than assuming it.

Expected Output / Verification

  • A resource emitting both validators returns 304 Not Modified when a request supplies a correct If-None-Match, even alongside a stale If-Modified-Since — confirming ETag precedence.
  • Last-Modified alone correctly returns 304 when If-Modified-Since matches or postdates the resource’s actual last-change time, and 200 OK with a fresh body otherwise.
  • CDN edge logs or debug headers show If-None-Match (not If-Modified-Since) in the upstream revalidation request whenever both validators were available at origin.

Edge Cases

  • Sub-second updates collapse under Last-Modified — two writes to the same resource within the same second produce an identical Last-Modified value, so a client relying solely on it will incorrectly treat the second version as unchanged. Only a content-hash ETag distinguishes them.
  • Clock skew degrades Last-Modified, not ETag — because ETag comparison is a pure string match independent of any clock, it is immune to the clock-skew failure modes that affect date-based validation; see Handling Clock Skew in Last-Modified Validation.
  • HTTP/1.1 vs HTTP/2 — the precedence rule and both conditional-header mechanisms are unaffected by transport version; the choice of validator is purely an application/origin-layer decision.
  • Legacy intermediaries that only understand dates — some very old caching proxies only implement If-Modified-Since. Emitting Last-Modified alongside ETag costs almost nothing and preserves compatibility with that minority of clients without weakening the guarantees modern clients get from ETag.

Frequently Asked Questions

Which validator takes precedence when both ETag and Last-Modified are present?

ETag takes precedence. RFC 9110 Section 13.2.2 requires a server that supports If-None-Match to evaluate that condition and ignore If-Modified-Since whenever both are sent on the same request.

Is Last-Modified ever more accurate than ETag?

No. Last-Modified is capped at one-second granularity by its HTTP-date format, so it cannot express two distinct changes to a resource that occur within the same second. A content-hash ETag has no such limit.

Should I always emit both validators?

Yes, when the cost of computing an ETag is low. Emitting both maximizes compatibility with older or simpler clients and intermediaries that only implement date-based validation, while modern clients still get the precision of ETag.

Which validator is cheaper to compute for large files?

Last-Modified is cheaper because it only requires a filesystem stat call. A content-hash ETag requires reading the entire file, though this cost can be eliminated by computing the hash once at build or deploy time rather than per request.


Back to ETag Generation and Validation Strategies