HTTP ETags are validators associated with a representation of a resource. They help clients make conditional requests and can reduce unnecessary transfer when the relevant representation has not changed. They are not automatically content hashes, freshness guarantees, or authorization tokens.
A correct design explains which representation the validator identifies and how the server evaluates conditions. This guide focuses on cache revalidation, comparison strength, response behavior, and privacy so an opaque tag does not become a misleading shortcut around normal HTTP semantics.
Define the representation being validated
A resource can have multiple representations depending on content negotiation, encoding, language, or application context. The validator must describe the representation actually returned through the relevant request path.
Do not generate one global tag while returning different tenant-specific bodies under the same URL. The application and cache configuration need appropriate separation. A conditional request must not cause one user’s response to stand in for another’s.
Record which changes should alter the validator. A database row version may be useful only if it covers every field and transformation that affects the response. A changed rendering template can change bytes without changing the source row.
Treat the tag as an opaque validator
An ETag can be generated through a supported application strategy; clients should not assume its internal format or derive permissions from it. The server owns the comparison contract. A tag that looks like a digest need not be a universal file checksum.
Avoid including private data directly in the tag. A short identifier can still expose internal state or enable correlation. Choose a representation identity without embedding secrets or unnecessary personal information.
Keep generation stable for the intended semantic model. A tag that changes on every request prevents useful revalidation, while a tag that never changes can validate stale content incorrectly. Measure the actual behavior.
Choose strong or weak semantics deliberately
A strong validator identifies a representation for strong comparison; a weak validator, marked with the documented prefix, can express semantic equivalence without claiming identical representation bytes.
Do not use weak tags in every conditional context as though they were interchangeable with strong tags. Different headers and operations have their own comparison rules. Review the intended use, including range or write conditions where applicable.
For revalidation with If-None-Match, the documented comparison behavior differs from strong precondition checks. The server should implement the relevant protocol semantics instead of a generic string inequality copied across all endpoints.
Return the correct conditional response
A client can send a validator through If-None-Match. For the relevant GET or HEAD semantics, a matching current representation can produce a 304 response rather than transferring the body again.
Keep the response metadata consistent with the selected representation and caching rules. A 304 is not simply an empty 200. It has defined behavior that caches use to update their stored response information.
Test matching and nonmatching tags, multiple validators, and the wildcard behavior relevant to the endpoint. A happy-path browser refresh does not validate the whole conditional-request contract.
Keep freshness and revalidation separate
Cache-Control defines caching and freshness behavior, while an ETag provides a validator for conditional requests. Neither replaces the other. A cache may use a fresh response without contacting the origin at all.
Decide when the client must revalidate and which caches may store the response. Public, private, and no-store requirements need deliberate treatment based on content sensitivity. Adding an ETag does not make confidential data safe in a shared cache.
Review intermediary behavior and Vary where response selection depends on request headers. A correct origin validator can still be undermined by an incorrect cache key. Test through the actual delivery path.
Preserve authorization on conditional requests
Authenticate and authorize the request according to the endpoint’s policy even when the client supplies an old validator. A matching tag should not become a substitute for permission to access the resource.
Consider access changes and revoked sessions. A client that previously fetched content may later lose access. Returning a conditional success without checking current authority can reveal continued existence or incorrectly validate cached private content.
Keep object identity and tenant context in the request evaluation. A validator copied from another resource should not cause a privileged response. Opaque tags are state hints, not bearer credentials.
Review transformation and deployment boundaries
Compression, proxies, and application rendering can affect representation bytes. Confirm which layer generates the validator and whether later transformations preserve its intended meaning. Avoid inconsistent tagging across origin replicas.
A deployment changing output formatting may require different strong validators even if the underlying business values remain the same. Conversely, a weak semantic tag can be appropriate only when its equivalence claim is intentional and correct.
Include negative tests across replicas and encodings. A cache receiving alternating tags for equivalent requests can lose efficiency, while a reused strong tag for different bytes can violate the stated contract.
Validate correctness before measuring savings
Test the first full response, an unchanged conditional response, a changed resource, access revocation, and representation variation. Verify status, body presence, caching headers, and validator identity through the real client path.
Measure reduced transferred bytes and origin work separately. A 304 can save body transfer while the server still performs an expensive query or rendering step to decide whether the representation changed.
For a user-specific dashboard, keep authentication current, cache scope private where appropriate, and generate validators from the complete response version. Revalidation then improves efficiency without crossing user boundaries or pretending that cached data is permanently authorized.
Keep conditional response generation race-aware
The selected validator and body should describe a consistent representation. If the resource changes between independently generating the tag and rendering the body, the response can advertise a validator for different content.
Use a suitable snapshot or version-aware rendering approach for the application. Test concurrent updates in a controlled environment and verify subsequent conditional requests behave correctly. A tag calculated from a fresh row followed by a body from stale cached state is not a coherent representation contract.
Frequently asked questions
Is an ETag always a content hash?
No. It is an opaque validator whose generation and comparison semantics belong to the server and protocol.
Does an ETag define freshness?
No. Freshness and storage behavior require the relevant caching headers and policy.
Where are comparison rules explained?
Read MDN’s ETag reference and If-None-Match reference.
For a complementary workflow, read Cache-Control Headers: 7 Checks for Safer Web Caching.