
When you inspect a website delivered through a CDN, you may see 304 Not Modified in the browser's Network panel. A 304 response is not an error and does not mean the CDN failed to return the file. It means the client already has a cached copy and the server has confirmed that the copy is still valid, so the response body does not need to be transferred again.
This validation process usually relies on ETag or Last-Modified. Both validators reduce repeated data transfer, but they use different comparison methods. If the origin, CDN, and browser handle them inconsistently, users may see stale content, every request may reach the origin, or different edge locations may behave differently.
How Does a 304 Not Modified Response Happen?
On the first request, the server normally returns 200 OK, the complete response body, and cache headers:
HTTP/1.1 200 OK Cache-Control: public, max-age=300 ETag: "page-v18" Last-Modified: Wed, 26 Aug 2026 02:10:00 GMT
After storing the resource, the browser can send the previous validator when the cached response becomes stale:
GET /assets/app.js HTTP/1.1 If-None-Match: "page-v18" If-Modified-Since: Wed, 26 Aug 2026 02:10:00 GMT
If the representation has not changed, the server can return 304 without the normal resource body. The browser reuses its local copy. This saves downstream bandwidth, although the request still creates a network round trip and processing work.
ETag vs Last-Modified: What Is the Difference?
ETag identifies a resource version
An ETag is an identifier generated for a representation. It may be based on a content hash, version number, file metadata, or an application rule. During revalidation, the client returns it in If-None-Match. The ETag must change whenever the delivered representation changes.
A strong ETag indicates byte-for-byte equivalence. A weak ETag starts with W/ and indicates semantic equivalence even if the exact bytes differ. Weak validators can work for ordinary cache revalidation, but byte-sensitive operations such as some range requests require extra care.
Last-Modified validates by time
Last-Modified records when a resource was last changed. The client sends it back in If-Modified-Since. It is simple and commonly generated for static files, but HTTP dates normally have one-second precision. File timestamps may also change during copying or deployment even when content does not.
What if both validators are present?
A response can include both. When the corresponding conditional headers arrive together, If-None-Match takes precedence for this type of validation. The origin and CDN should preserve validators consistently instead of mixing unrelated versions.
Does the Browser, CDN, or Origin Return the 304?
The browser may revalidate against the CDN edge. If the edge has a usable stored response and can evaluate the validator, it may answer without contacting the origin. If the edge object is stale or needs confirmation, the CDN can send a conditional request upstream.
A 304 visible in the browser does not prove that the origin was contacted. Check CDN logs, cache-status headers, origin logs, and the request path together.
Why Can a CDN Keep Serving Old Content?
The ETag does not change with the content
If an application generates the same ETag for different versions, a conditional request may incorrectly receive 304. Generate the validator from the actual representation or a version value that changes with it.
Compression produces inconsistent representations
Gzip, Brotli, and uncompressed responses are not necessarily byte-identical. Review Content-Encoding, Vary: Accept-Encoding, the cache key, and the stage at which ETags are generated.
The cache key does not match Vary
A response may vary by language, compression, selected headers, cookies, or query strings. If the CDN cache key ignores a dimension used by the origin, one cached variant can be validated for another request.
Deployment timestamps are unreliable
Copying files can preserve an old timestamp or assign a new timestamp when bytes are unchanged. Distributed origins can also report different times. Last-Modified should come from a stable source of truth.
Invalidation is mistaken for validator repair
Invalidating a CDN object removes an edge copy, but it does not fix an origin that continues to send an incorrect ETag, Last-Modified value, Cache-Control directive, or representation.
How to Troubleshoot 304 Responses
Record the first 200 response. Save the URL, body hash, ETag, Last-Modified, Cache-Control, Age, Vary, Content-Encoding, and cache-status headers.
Repeat with a conditional request. Send
If-None-MatchorIf-Modified-Sinceexplicitly.Compare the CDN and origin. If access controls allow it, test the same resource at the origin with the correct Host header and TLS hostname.
Check cache-key dimensions. Compare query strings, cookies, forwarded headers, compression, language, and device variants.
Change the resource deliberately. Compare old and new validators, timestamps, status codes, and body hashes.
curl -I https://example.com/assets/app.js curl -I https://example.com/assets/app.js -H 'If-None-Match: "page-v18"' curl -I https://example.com/assets/app.js -H 'If-Modified-Since: Wed, 26 Aug 2026 02:10:00 GMT'
How Should the Cache Headers Be Configured?
Static resources can use both validators as long as both follow the real representation. Fingerprinted assets such as app.7f3c1a.js can usually use a long cache lifetime because a content change creates a new URL.
HTML and dynamic APIs need policies based on their behavior. Public cacheable HTML may use a shorter max-age followed by revalidation. Private user responses should use suitable private or no-store directives and must not enter a shared CDN cache simply to reduce origin requests.
If a representation changes by language, encoding, or headers, configure Vary and the CDN cache key consistently. A correct ETag cannot compensate for validating the wrong variant.
Do More 304 Responses Mean Better CDN Performance?
Not necessarily. A 304 avoids the full response body but does not eliminate the request or round trip. For fingerprinted static assets that are safe to cache for a long time, using a fresh local copy without revalidation is often more efficient.
Evaluate cache hit ratio, origin request volume, downstream traffic, update frequency, and the time required for users to receive new content instead of optimizing only for the number of 304 responses.
Frequently Asked Questions
Does a 304 count as a CDN request?
It normally still represents an HTTP request and may count toward request usage. Whether it reaches the origin depends on whether the edge can validate locally. Billing follows the provider's current terms.
Do I still need Cache-Control when using ETag?
Yes. Cache-Control determines whether a response may be stored, how long it remains fresh, and when it must be revalidated. ETag decides whether the representation changed during validation.
Does no-cache mean do not store?
No. no-cache generally allows storage but requires revalidation before reuse. Use an appropriate no-store policy when a sensitive response should not be stored.
Will clearing the CDN cache fix every 304 problem?
No. If the origin keeps generating incorrect validators or headers, the replacement edge object can reproduce the same issue.
Conclusion
A 304 response is a successful cache revalidation result, not a failed download. Troubleshooting should follow the request through the browser cache, CDN edge, and origin. ETag must follow the delivered representation, Last-Modified must come from a reliable timestamp, and Cache-Control plus Vary must define when a response is reused and which requests share the same object.
CloudFlew provides CDN services based on AWS CloudFront. Before applying one caching rule to an entire website, separate the requirements for fingerprinted assets, HTML, and APIs, then test the 200, 304, and cache-refresh paths in a controlled environment.
References
RFC 9110, HTTP Semantics: https://www.rfc-editor.org/rfc/rfc9110
MDN Web Docs, ETag: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag
MDN Web Docs, Last-Modified: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Last-Modified
MDN Web Docs, 304 Not Modified: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304
AWS CloudFront Developer Guide, Request and response behavior for custom origins: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html
Sources checked on August 26, 2026.