CDN Caching Explained
Understand how CDN caching works, how browsers and edge servers cache content, how TTL and HTTP headers control caching, and how to invalidate stale resources.
CDN caching is one of the main reasons modern websites can deliver static files quickly to users around the world. Instead of requesting every image, stylesheet, JavaScript file or other resource from the origin server, a content delivery network can store copies of frequently requested resources on edge servers located closer to users.
When caching is configured correctly, repeated requests can be served from an edge location without reaching the origin server. This reduces latency, lowers origin traffic and helps websites handle more simultaneous visitors. However, caching also introduces an important challenge: deciding how long content should remain cached and how stale content should be replaced.
What Is CDN Caching?
CDN caching is the process of temporarily storing HTTP responses on CDN edge servers so that subsequent requests for the same resource can be served from the edge instead of the origin server.
User
↓
CDN Edge Server
↓
Cache HIT → Return cached response
Cache MISS
↓
Origin Server
↓
CDN stores response
↓
User receives responseThe cached resource might be an image, JavaScript bundle, CSS file, font, HTML document, JSON response or another HTTP resource. Exactly what gets cached depends on the CDN configuration, request properties and HTTP caching headers.
Why CDN Caching Matters
Without caching, every request for a resource may have to travel to the origin server. For a globally distributed website, this can increase latency and put unnecessary load on the infrastructure.
- Reduce response latency.
- Decrease traffic to the origin server.
- Improve website scalability.
- Reduce repeated downloads from the origin.
- Serve popular resources closer to users.
- Improve the performance of static assets.
- Help absorb traffic spikes.
How a CDN Cache Works
A CDN usually sits between users and the origin server. When a user requests a cacheable resource, the CDN checks whether an appropriate cached response already exists at the selected edge location.
First request
User → CDN → Origin
↓
Store response
↓
User ← CDN ← Origin
Later request
User → CDN
↓
Cache HIT
↓
User ← CDNThe first request may require communication with the origin. Once the response is cached, later requests can often be served directly from the CDN edge.
Cache HIT vs Cache MISS
A cache hit occurs when the CDN can satisfy a request using a valid cached response. A cache miss occurs when the requested resource is not currently available in the appropriate cache or cannot be served from the existing cached response.
| Result | Meaning | Typical behavior |
|---|---|---|
| Cache HIT | Valid cached response exists | CDN returns cached content |
| Cache MISS | No suitable cached response | CDN requests content from origin |
| Revalidation | Cached response may be stale | CDN checks with origin |
| Bypass | Caching is disabled or skipped | Request goes to origin |
What Is TTL?
TTL, or time to live, determines how long a cached resource can remain fresh before it needs to be considered stale or revalidated. In HTTP caching, TTL is commonly influenced by response headers such as Cache-Control and Expires.
Cache-Control: public, max-age=3600In this example, max-age=3600 indicates a freshness lifetime of 3,600 seconds, or one hour, for caches that follow this directive.
| TTL | Typical implication |
|---|---|
| Short | Content updates are reflected more quickly |
| Medium | Balance between freshness and cache efficiency |
| Long | Excellent cache efficiency for stable resources |
| Very long | Best for immutable, versioned assets |
Cache-Control
Cache-Control is one of the most important HTTP response headers for controlling caching behavior. It contains directives that tell browsers and shared caches how a response can be stored and reused.
Cache-Control: public, max-age=3600The public directive indicates that the response may be stored by shared caches, while max-age specifies how long the response can remain fresh.
Common Cache-Control Directives
| Directive | Purpose |
|---|---|
| public | Allows shared caches to store the response |
| private | Response is intended for a private cache |
| no-cache | Requires validation before reuse |
| no-store | Do not store the response |
| max-age | Defines freshness lifetime |
| s-maxage | Defines freshness lifetime for shared caches |
| must-revalidate | Requires validation after becoming stale |
| immutable | Indicates that the resource will not change |
| stale-while-revalidate | Allows stale content while refreshing |
Public vs Private Caching
The distinction between public and private caching is important for resources that may contain user-specific information. Public shared caches can serve the same response to multiple users, while private caches such as a browser cache are associated with an individual user.
Cache-Control: public, max-age=86400
Cache-Control: private, max-age=300no-cache vs no-store
The names no-cache and no-store are often confused. no-store means the response should not be stored. no-cache does not mean that storage is forbidden; instead, a cache must validate the stored response before reusing it when required by the directive.
| Directive | Meaning |
|---|---|
| no-cache | Stored response must be validated before reuse |
| no-store | Response should not be stored |
s-maxage
The s-maxage directive is designed for shared caches such as CDNs. It can specify a different freshness lifetime for shared caches than max-age.
Cache-Control: public, max-age=60, s-maxage=3600Here the browser-oriented max-age can be one minute while the shared CDN cache can consider the response fresh for one hour, depending on the cache implementation.
ETag and Cache Revalidation
An ETag is a response header containing an identifier associated with a particular representation of a resource. It can be used during conditional requests to determine whether the cached version is still current.
ETag: "abc123"A client or cache can later send the value using the If-None-Match request header. If the resource has not changed, the server can respond with HTTP 304 Not Modified instead of sending the full response body again.
If-None-Match: "abc123"304 Not Modified
A 304 Not Modified response indicates that the cached representation can still be used. The server does not need to transmit the complete resource body again, which can reduce bandwidth and improve efficiency.
Client
↓
If-None-Match: "abc123"
↓
Server
↓
ETag still matches
↓
304 Not Modified
↓
Use cached responseLast-Modified and If-Modified-Since
Last-Modified is another mechanism for cache validation. A server can provide the time at which a resource was last changed, and a later request can use If-Modified-Since to ask whether the resource has changed since that time.
Last-Modified: Sat, 23 Aug 2026 10:00:00 GMT
If-Modified-Since: Sat, 23 Aug 2026 10:00:00 GMTETag and Last-Modified can both support conditional requests. Which mechanism is used depends on the server and caching architecture.
Browser Cache vs CDN Cache
A browser cache and a CDN cache both store HTTP responses, but they operate at different locations. The browser cache is local to an individual user, while the CDN cache is shared infrastructure distributed across edge locations.
| Feature | Browser Cache | CDN Cache |
|---|---|---|
| Location | User's device | CDN edge server |
| Shared between users | No | Usually yes |
| Controlled by | Browser and HTTP headers | CDN and HTTP headers |
| Main benefit | Avoid network requests | Serve content closer to users |
| Origin load reduction | Indirect | Direct |
Cache Keys
A CDN needs to determine which cached response corresponds to an incoming request. The information used to distinguish cached objects is commonly referred to as the cache key.
Depending on the CDN configuration, the cache key may consider the URL, query string, host, selected headers or other request properties. Two requests that produce different cache keys can therefore result in separate cached objects.
Query Strings and Caching
Query parameters can affect cache behavior. For example, these URLs may be treated as different cache entries depending on the CDN configuration.
/image.jpg?width=800
/image.jpg?width=1200This can be useful when query parameters genuinely change the generated resource, but unnecessary parameters can reduce cache efficiency by creating multiple cache variants for content that is otherwise identical.
Cache Invalidation
Cache invalidation is the process of removing or replacing cached content before its normal freshness lifetime expires. It is necessary when a resource changes but an existing cache entry would otherwise continue serving an older version.
- Purge a specific URL.
- Purge a group of URLs.
- Invalidate a cache tag or cache group.
- Wait for the configured TTL to expire.
- Change the resource URL.
- Deploy a new versioned asset.
Why Cache Invalidation Is Difficult
A cached resource may exist in multiple locations, including browsers and several CDN edge servers. Removing one cached copy does not necessarily mean that every previously stored copy disappears instantly.
For this reason, modern websites often combine explicit invalidation with versioned asset URLs. Instead of replacing an existing file while keeping exactly the same URL, a new filename or URL can identify the new version.
Cache Busting
Cache busting changes the resource URL when the content changes. Because caches use the URL as part of identifying a resource, a new URL can cause the CDN and browser to treat the updated asset as a separate resource.
/styles.css?v=1
/styles.css?v=2Another common approach is filename hashing, where the content version becomes part of the filename.
app.8f31c2.js
app.a92d10.jsBuild systems frequently use hashed filenames for JavaScript and CSS assets because they allow very long cache lifetimes while ensuring that changed content receives a new URL.
Immutable Assets
An immutable asset is a resource whose URL is designed to represent content that will not change. Versioned or content-hashed assets are good candidates for long cache lifetimes.
Cache-Control: public, max-age=31536000, immutableA one-year freshness lifetime can be appropriate for an asset whose URL changes whenever its contents change. It would be much riskier for a mutable file such as /app.js that is overwritten while keeping the same URL.
Caching Static Assets
Static assets are usually strong candidates for CDN caching because they can often be shared between many users and change less frequently than dynamic application responses.
| Resource | Typical caching approach |
|---|---|
| Hashed JavaScript | Long TTL |
| Hashed CSS | Long TTL |
| Images | Medium or long TTL |
| Fonts | Long TTL |
| Versioned files | Long TTL |
| HTML | Depends on deployment strategy |
| Personalized API response | Usually private or carefully controlled |
Caching HTML
HTML caching requires more careful planning than static assets because HTML often contains dynamic information. Some websites cache generated HTML at the CDN edge, while others use short TTLs or bypass shared caching for personalized pages.
Caching API Responses
API responses can be cached when the same response can safely be reused by multiple requests. Public APIs and read-only resources are often easier to cache than personalized responses.
Before caching an API response, consider whether the response depends on cookies, authorization headers, query parameters, user identity or other request-specific information.
CDN Caching and Cookies
Cookies can affect whether a response is safe and useful to cache. If a response changes depending on a user's session cookie, serving the same cached response to another user could expose incorrect or sensitive information.
Cache-Control Examples
# Cache for one hour
Cache-Control: public, max-age=3600
# Long-lived versioned asset
Cache-Control: public, max-age=31536000, immutable
# Private response
Cache-Control: private, max-age=300
# Do not store
Cache-Control: no-store
# Validate before reuse
Cache-Control: no-cachestale-while-revalidate
The stale-while-revalidate directive allows a cache to serve a stale response for a specified period while it retrieves a fresh version in the background. This can reduce perceived latency because users do not always have to wait for the cache to obtain an updated response.
Cache-Control: public, max-age=60, stale-while-revalidate=300With this strategy, the resource can be considered fresh for the configured max-age and may remain usable while revalidation occurs during the stale-while-revalidate window, subject to the behavior of the caches involved.
Cache-Control Headers vs CDN Configuration
HTTP cache headers provide standardized instructions, but CDNs can also have their own caching rules and configuration options. A CDN may override, extend or otherwise customize caching behavior according to its configuration.
For this reason, debugging caching problems requires checking both the response headers and the CDN configuration. A correct Cache-Control header does not guarantee that every CDN setting will behave exactly as expected if explicit edge rules override the default behavior.
How to Check CDN Caching
The first step in troubleshooting CDN caching is inspecting the HTTP response. Browser developer tools, command-line clients and HTTP header inspection tools can reveal cache-related headers and other information returned by the server or CDN.
curl -I https://example.com/app.jsLook for Cache-Control, ETag, Last-Modified, Age and CDN-specific cache status headers. The exact header names and values vary between providers.
The Age Header
The Age response header can indicate how long a response has been stored in a shared cache. It can be useful when diagnosing whether a response came from a cache and how old that cached response is.
Age: 742An Age value of 742 indicates approximately 742 seconds of age for the cached response, when the header is provided and interpreted according to HTTP caching rules.
CDN-Specific Cache Status Headers
Many CDN providers expose additional response headers that indicate whether a request was served from an edge cache or forwarded to the origin. The exact header varies by provider, so these headers should be interpreted using the documentation for the CDN being used.
| Signal | What it can indicate |
|---|---|
| Age | Approximate age of a shared cached response |
| Cache-Control | Caching and freshness instructions |
| ETag | Resource representation identifier |
| Last-Modified | Last modification time |
| CDN status header | Provider-specific cache result |
Common CDN Caching Problems
- Users receive outdated files.
- Cache hit rate is lower than expected.
- Different query strings create unnecessary cache entries.
- Dynamic responses are accidentally cached.
- Static assets have unnecessarily short TTLs.
- Changed assets are not invalidated correctly.
- Browser and CDN caches behave differently.
- CDN rules override expected HTTP caching behavior.
How to Improve Cache Hit Rate
A high cache hit rate means that more requests can be served from the CDN rather than reaching the origin. Improving it usually requires reducing unnecessary cache variations, selecting appropriate TTLs and ensuring that resources are actually cacheable.
- Use appropriate Cache-Control headers.
- Version static assets.
- Avoid unnecessary cache-key variations.
- Keep frequently requested resources cacheable.
- Use long TTLs for immutable assets.
- Avoid accidental cache bypasses.
- Review cookies and authorization behavior.
- Monitor cache hit and miss rates.
CDN Caching Strategy by Resource Type
There is no single cache policy that works for every resource. A practical strategy assigns caching behavior based on how frequently the resource changes, whether it is shared between users and whether the URL is versioned.
| Resource | Suggested strategy |
|---|---|
| Content-hashed JS/CSS | Very long TTL |
| Versioned images | Long TTL |
| Fonts | Long TTL |
| Public static JSON | Medium or long TTL |
| Frequently changing HTML | Short TTL or controlled caching |
| Personalized HTML | Private or bypass shared cache |
| Authenticated API response | Usually private or bypass |
CDN Caching Best Practices
- Use Cache-Control to explicitly define caching behavior.
- Use long cache lifetimes for immutable, versioned assets.
- Use filename hashing for build-generated assets.
- Avoid publicly caching personalized responses.
- Use ETags or Last-Modified when revalidation is useful.
- Keep cache keys as simple as the application allows.
- Avoid unnecessary query-string variations.
- Plan cache invalidation before deploying frequently changing resources.
- Inspect response headers when debugging cache behavior.
- Monitor cache hit rates and origin traffic.
Frequently Asked Questions
What is CDN caching?
CDN caching stores copies of HTTP resources on edge servers so that subsequent requests can be served closer to users without contacting the origin server every time.
What is a CDN cache hit?
A cache hit occurs when the CDN has a valid cached response that can satisfy the request without fetching the resource from the origin.
What is a cache miss?
A cache miss occurs when the CDN does not have a suitable cached response, so it generally needs to retrieve the resource from the origin or another upstream cache.
What does max-age mean?
The max-age directive defines how many seconds a cached response can remain fresh according to HTTP caching rules.
What is the difference between no-cache and no-store?
no-cache allows a response to be stored but requires validation before reuse when applicable, while no-store instructs caches not to store the response.
What is an ETag used for?
An ETag identifies a particular representation of a resource and can be used with If-None-Match to efficiently validate whether a cached response is still current.
How do I clear a CDN cache?
Depending on the CDN, you can purge specific URLs, groups of resources or cache tags. Another approach is waiting for the configured cache lifetime to expire or changing the resource URL.
Why are users still seeing an old file after deployment?
The old file may still exist in a browser or CDN cache. Long TTLs, unchanged URLs and incomplete invalidation can all cause an older response to remain available.
How can I avoid stale JavaScript and CSS?
Use content-hashed or versioned filenames and give those immutable assets long cache lifetimes. When the content changes, generate a new URL.
Should HTML be cached by a CDN?
It can be, but the policy depends on whether the HTML is public, dynamic or personalized. Public static HTML can often be cached, while user-specific pages require much more careful handling.
Can a CDN cache API responses?
Yes, if the responses are safe to share and the caching policy is configured correctly. Personalized or sensitive responses generally require private caching or a cache bypass.
Helpful Web Tools
A Cache-Control Generator helps create HTTP Cache-Control directives, a CDN URL Generator assists with constructing CDN resource URLs, an HTTP Header Viewer displays response headers, an ETag Generator creates ETag values for resources, and an HTTP Header Generator helps build common HTTP headers for web applications.
Conclusion
CDN caching improves website performance by storing frequently requested resources closer to users and reducing unnecessary requests to the origin server. The effectiveness of caching depends on several factors, including cache keys, TTL, Cache-Control directives, validation headers, URL versioning and CDN configuration.
The most reliable strategy is to match caching behavior to the resource. Immutable, versioned JavaScript, CSS, images and fonts can usually use long cache lifetimes, while dynamic and personalized responses require more conservative policies. By combining appropriate HTTP headers, versioned URLs, safe invalidation strategies and regular cache monitoring, developers can achieve fast delivery without sacrificing correctness or security.