How to Use 304 Not Modified in REST APIs
Use the
304 Not Modified status code in your REST API to tell clients that the requested resource has not changed since their last request. This avoids sending the full response body again, saving bandwidth and improving performance. Implement it by checking request headers like If-Modified-Since or If-None-Match and responding with 304 when appropriate.Syntax
The 304 Not Modified response is sent without a message body. It relies on conditional request headers from the client:
If-Modified-Since: Date/time of the last known modification.If-None-Match: ETag value representing the resource version.
If the resource has not changed since the date or ETag provided, the server responds with 304 Not Modified and no body.
http
HTTP/1.1 304 Not Modified Date: Wed, 21 Oct 2020 07:28:00 GMT ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Example
This example shows a simple Node.js Express server that uses 304 Not Modified to avoid sending unchanged data.
javascript
import express from 'express'; const app = express(); const resource = { data: 'Hello, world!', lastModified: new Date('2024-01-01T12:00:00Z'), etag: '12345abcde' }; app.get('/resource', (req, res) => { const ifModifiedSince = req.headers['if-modified-since']; const ifNoneMatch = req.headers['if-none-match']; if ((ifModifiedSince && new Date(ifModifiedSince) >= resource.lastModified) || (ifNoneMatch && ifNoneMatch === resource.etag)) { res.status(304).end(); return; } res.setHeader('Last-Modified', resource.lastModified.toUTCString()); res.setHeader('ETag', resource.etag); res.send(resource.data); }); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });
Output
Server running on http://localhost:3000
Common Pitfalls
- Not setting
Last-ModifiedorETagheaders properly, which makes conditional requests fail. - Sending a response body with
304, which is against the HTTP specification. - Ignoring client headers
If-Modified-SinceandIf-None-Match, causing unnecessary data transfer. - Using inaccurate timestamps or ETag values, leading to wrong cache validation.
javascript
/* Wrong: Sending body with 304 */ res.status(304).send('This should not be sent'); /* Right: No body with 304 */ res.status(304).end();
Quick Reference
| Header | Purpose |
|---|---|
| If-Modified-Since | Client asks if resource changed since this date |
| If-None-Match | Client asks if resource ETag matches |
| Last-Modified | Server tells when resource was last changed |
| ETag | Server provides a unique version identifier |
| 304 Not Modified | Server says resource unchanged, no body sent |
Key Takeaways
Use 304 Not Modified to save bandwidth by not resending unchanged resources.
Check client headers If-Modified-Since and If-None-Match to decide when to send 304.
Always set Last-Modified and ETag headers for proper cache validation.
Never send a response body with a 304 status code.
Accurate timestamps and ETags ensure correct cache behavior.