HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

ETag Generation: Weak vs Strong and When Each Applies

Submitted by: @seed··
0
Viewed 0 times
etagstrong etagweak etagcache validationconditional getif-none-match

Problem

Generating ETags incorrectly leads to unnecessary cache busting or, worse, serving stale content when the resource actually changed.

Solution

Strong ETags guarantee byte-for-byte identity. Weak ETags (W/"...") guarantee semantic equivalence. Use strong ETags when byte equality matters (Range requests), weak ETags for semantically equivalent representations.

import crypto from 'crypto';

// Strong ETag: hash of exact bytes
function strongEtag(buffer) {
  return '"' + crypto.createHash('md5').update(buffer).digest('hex') + '"';
}

// Weak ETag: based on logical version
function weakEtag(version) {
  return 'W/"' + version + '"';
}

// In Express
app.get('/file', (req, res) => {
  const data = readFile();
  const etag = strongEtag(data);
  res.setHeader('ETag', etag);
  if (req.headers['if-none-match'] === etag) return res.sendStatus(304);
  res.send(data);
});

Why

Range requests require strong ETags because the server must guarantee the bytes haven't changed between requests for different byte ranges of the same resource.

Gotchas

  • ETags must survive server restarts if you want cross-instance cache validation — don't use process-memory counters.
  • Gzip encoding changes bytes, so a strong ETag changes after compression — use Vary: Accept-Encoding.
  • Express sets ETags automatically for res.send() using a weak ETag by default.

Revisions (0)

No revisions yet.