http-caching-guide
http-caching-guide copied to clipboard
Short Guide for Modern HTTP Caching
http-caching-guide
Short Guide for Modern HTTP Caching
Cache-Control
Controls how responses should be cached.
Directives
no-store
Do NOT cache the response.
Cache-Control: no-store
no-cache
Revalidate cache before use (see Cache Revalidation for more info).
Browser will send a request to validate if the cached data can be used. This can reduce bandwidth but still requires a roundtrip to validate the cached response.
Cache-Control: no-cache
max-age
Set the maximum amount of time (in seconds) that the resource will be cached.
Browser will use cached response without sending any request (from disk cache).
Cache-Control: max-age=3600
public
Response can be cached in shared cache (Reverse Proxy, CDN, etc.)
Note: most of the time, you don’t need to use
publicas it can be inferred by other caching directives, such asmax-age. But check with CDN document first.
Cache-Control: max-age=3600
equals to
Cache-Control: public, max-age=3600
private
Response is intended for one user CAN NOT be cached in shared cache.
Cache-Control: private, max-age=3600
immutable
Prevents cache revalidation when clicking Refresh button (which normally causes revalidation on all resources).
Cache-Control: max-age=31536000, immutable
Cache-Control Summary
Static files with unique file name (ex. with hash in file name)
Cache-Control: public, max-age=31536000, immutable
MPA (generate HTML)
Cache-Control: no-store
Why not no-cache ?
Because MPA server usually send Set-Cookie to rolling cookie expiration time,
and 304 Not Modified should not send other header than cache information.
RFC 7372 - Section 4.1
Web Pages (static HTML)
Cache-Control: no-cache
SPA index.html
Cache-Control: no-cache
Cache Revalidation
Last-Modified and ETag can be used for conditional requests, but not included in this article.
When no-cache directive is used,
at least one of these headers must be set to trigger cache revalidation.
Last-Modified
Time that the resource has been last modified.
Normally used for static files.
Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
ex.
Last-Modified: Tue, 18 Sep 2018 11:12:03 GMT
If browser has cached the response, it will send a request to validate cache with
If-Modified-Since: Tue, 18 Sep 2018 11:12:03 GMT
If the server has a newer file, then it sends the new file contents and new Last-Modified header
HTTP/1.1 200 OK
Date: Tue, 18 Sep 2018 22:00:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 7
Last-Modified: Tue, 18 Sep 2018 20:00:00 GMT
Content
If file has not been modified since, then it returns 304 status code without body.
HTTP/1.1 304 Not Modified
Date: Tue, 18 Sep 2018 22:00:00 GMT
ETag
Like Last-Modified but ETag has more accuracy.
Used when server does not know resource's last modified date or when a resource could change more than once in a second.
ETag is like a fingerprint of resource, and a server must generate a new ETag when the resource’s contents changed.
ETag can be generated using hash of response body, UUID, or anything that results in a unique string when resource contents changed.
Browser will send If-None-Match to server to validate cache.
ETag has Weak and Strong validator.
Weak
A weak ETag is used to validate only body of response, when response body changed, ETag value will change.
ETag: W/"value"
Example
ETag: W/"abcde"
Strong
A strong ETag is used to validate both response body and headers.
Even if body is not changed but header is changed, a strong ETag must be changed to a new value.
Use-cases: To cache byte-range response.
ETag: "value"
Example
ETag: "abc1" # for gzip
ETag: "abc2" # for br
Comparison
| ETag 1 | ETag 2 | Strong Comparison | Weak Comparison |
|---|---|---|---|
| W/"1" | W/"1" | no match | match |
| W/"1" | W/"2" | no match | no match |
| W/"1" | "1" | no match | match |
| "1" | "1" | match | match |
(from RFC-7232)
ETag Summary
Use Strong ETag unless you know what you're doing 😁
Ex. you don't care about
Content-EncodingContent-LanguageRangeSet-CookieVary- etc.
then you can use Weak ETag