Technical

HTTP 304

Also called Not Modified.

HTTP 304 is the status a server returns to say the copy a browser already holds is still valid, so no body is sent. It answers a conditional request.

How it is measured

The browser sends `If-None-Match` with the ETag from its earlier copy, or `If-Modified-Since` with a date. If nothing changed, the server replies `304 Not Modified` with headers only, usually a few hundred bytes.

A 304 costs a round trip but almost no transfer. In logs a healthy static asset shows 200 on first visits and 304 on repeats, with the 304 share rising over the days after a deploy.

Worked example

A 380 KB `app.js` on a docs site is revalidated 9,200 times in a day. 8,700 return 304 at about 300 bytes each, and 500 return 200 after a deploy changed the file. That is 190 MB for the 200s and 2.6 MB for the 304s.

Had the file been fingerprinted and sent with `Cache-Control: max-age=31536000, immutable`, those 8,700 requests would never have left the browser.

How it differs

An HTTP 304 is the result of validating with an ETag or a date: the client asked whether the file changed. The ETag is the version label the server issued, and the 304 is the answer. A 304 carries no body and is not an error.

Common errors

Treating 304 as a failure in uptime checks. Sending a body with it. Using ETags that differ between servers in a cluster, so validation always fails. Sending no `Cache-Control`, so browsers guess. Counting 304s as extra page loads. Forgetting that a CDN can answer 304 on its own.

In practice

Open DevTools with cache enabled and reload a page. Static files should show 304 or come from disk cache. Use fingerprinted filenames with a long max-age for assets and ETags for HTML, and make ETags identical across servers.

See also

ETag, Cache-Control

Sources

Count this on a real site.

Watch my website