Cache-Control: Cheat Sheet.
The Cache-Control
header sets rules for how web pages are stored in browser and CDN caches. It tells them how to save pages and when to check if the pages need to be updated from the original server.
Client <------ CDN <------ Server
↓ ↓ ↓
[Web Browser] [Shared Cache] [Origin Server]
Directives:
- no-store: The browser, CDN, and server are disallowed from storing any version of the returned response.
Client <------ CDN <------ Server
✗ ✗
- no-cache: The browser or CDN can store the response but must revalidate with the origin before serving it.
Client <------ CDN <------ Server
↓ ↓
Revalidate Revalidate
- private: The response is intended only for a single user (browser) and must not be stored by a shared cache (CDN).
Client <------ CDN <------ Server
✓ ✗
- public: The response may be stored by any cache including the browser and CDN.
Client <------ CDN <------ Server
✓ ✓
- max-age=<seconds>: Specifies the max amount of time a resource is considered fresh by the browser or CDN.
Client <------ CDN <------ Server
max-age max-age
- s-maxage=<seconds>: Similar to max-age but applies only to shared caches (CDN).
Client <------ CDN <------ Server
s-maxage
- must-revalidate: Once a resource becomes stale, caches (browser or CDN) must not use their stale copy without successful validation with the server.
Client <------ CDN <------ Server
↓ ↓
Revalidate Revalidate
- proxy-revalidate: Similar to must-revalidate but does not apply to private user agent caches (browser).
Client <------ CDN <------ Server
↓
Revalidate
- no-transform: The browser, CDN, or any intermediary must not transform the payload of the response.
Client <------ CDN <------ Server
✗ ✗
Transform Transform
- stale-while-revalidate=<seconds>: The browser or CDN can serve a stale response while it revalidates in the background.
Client <------ CDN <------ Server
↓ ↓
Serve Stale Serve Stale
Revalidate
- stale-if-error=<seconds>: The browser or CDN can serve a stale response if the server is unavailable.
Client <------ CDN <------ Server
↓ ↓
Serve Stale Serve Stale
Error Occurs
Note: Directives can be combined in a single Cache-Control header and they are case-insensitive.
Examples:
-
Public Cache with 1 day max age
- The response can be stored by any cache (browser or CDN) and is considered fresh for 1 day.
Cache-Control: public, max-age=86400
-
Private Cache with 1-hour max age
- The response is intended for a single user and can be stored by the browser, but not shared caches like CDNs. It’s considered fresh for 1 hour.
Cache-Control: private, max-age=3600
-
No Cache
- The response can be stored by the browser or CDN, but they must revalidate with the server before serving it.
Cache-Control: no-cache
-
No Store
- The response must not be stored by any cache (browser, CDN, or server).
Cache-Control: no-store
-
Fresh for 1 hour, revalidate after that
- The response is considered fresh for 1 hour, after which the cache must revalidate with the server before serving it.
Cache-Control: max-age=3600, must-revalidate
-
Public Cache, no transformation
- The response can be stored by any cache (browser or CDN), but it must not be transformed by any intermediary.
Cache-Control: public, no-transform
-
Shared Cache with 2 hours max-age, private cache with 1-hour max age
- The response can be stored by a shared cache (CDN) and is considered fresh for 2 hours. For private caches (browser), it’s considered fresh for 1 hour.
Cache-Control: s-maxage=7200, max-age=3600
-
Stale while revalidating for 1 hour
- The browser or CDN can serve a stale response while it revalidates with the origin in the background for up to 1 hour.
Cache-Control: stale-while-revalidate=3600
-
Stale while revalidating for 1 hour, serve stale on error for 2 hours
- The browser or CDN can serve a stale response while it revalidates with the origin in the background for up to 1 hour. If an error occurs during revalidation, the stale response can still be served for an additional 2 hours.
Cache-Control: stale-while-revalidate=3600, stale-if-error=7200
Express Example:
The code snippet below sets caching rules for the response. It allows any cache to store the response (public
). The response is considered current for 24 hours when cached by a browser (max-age=86400
), and for 2 hours when stored by shared caches, such as CDNs (s-maxage=7200
).
Additionally, if the response is outdated, both the browser and CDN can still temporarily deliver the old response while they update their cache with a new one, for up to 1 hour (stale-while-revalidate=3600
).
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.set(
'Cache-Control',
'public, max-age=86400, s-maxage=7200, stale-while-revalidate=3600'
);
res.send('Hello World');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});