- Works only for safe HTTP methods, say like GET and HEAD, methods that shouldn't mutate application state.
- Browser (private and public)
- Proxy (public)
- Gateway/Reverse Proxy (public)
-
Is content reusable? No?
no-store -
Should cache be revalidated each time?
no-cache -
Cacheable by intermediate caches?
public, elseprivate -
What is the age?
max-ageors-maxagefor shared -
Does content have multiple representations based on request encoding, host or agent?
VaryHeader, say onAccept-Encoding,User-Agent -
ETag,Last-Modified,Expires -
Does content has references resources that could be updated?
no-cachewith smallmax-ageon main with version suffices on files. -
Minimize churn by stripping out frequently updated parts to separate end points
-
Page has fragments that should be refreshed more often? Say homepage should be cached for 60 minutes while sidebar for 5 minutes?
Edge Side Includes(ESI) -
Setting one year as cache age is a really bad idea. A day should be more than enough for most scenarios.
- Quoting Mobify
If your servers can't stand to have your CDNs ask once a day if your profile picture has changed you should upgrade your servers.
unless a way to refresh stale assets is used (say version/hash appended file names, etc).
- Use
ExpiresorCache-Control'smax-age. - Client only pings back when the content has expired.
- Could serve stale content if expiration had a long value but minimize load on server
Last-ModifiedorETag- Client pings back at each request to check if content has changed and server should response with HTTP304 with an empty body if it hasn't.
- Adds load on server for each validation request, could be expensive depending on how the validation is verified
- Server can provide overridden values in response even when responding as HTTP304.
- Purge
- Purge all variants of a url on gateway by issuing a PURGE request.
- Refresh
- Invalidate and pull latest version of a url. Doesn't impact variants
- Banning
- Invalidate multiple urls by using regex
- Cache Tagging
- Tag content so all urls containing a specific tagged content can be invalidated at the same time
- Unique Representation of a resource
- Client sends
If-None-Match, with theETagvalue from the version client has, to server when asking for validation.
- GMT Date time
- Client sends
If-Modified-Sincewhen asking for validation
- max-age
- How long the content shall be cached for
- Relative to
Date, notLast-Modified - max-age=0 tells clients that they should revalidate the content.
- Sending this from client to server would trigger revalidation on all intermediate shared caches
- Overrides Expires header
- s-maxage
- Same as max-age but for shared cache endpoints and overrides max-cache
- Usually greater than max-age
- public/private
- Should the content be cached at shared cache endpoints or not
- must-revalidate
- Regards max-age and only asks for revalidation after the max-age has passed.
- no-cache
- Client must revalidate each time (notice how it is must and not should as in the case of max-age=0) and serve from cache only if validation is successful
- Does not regard the max-age, acts as must-revalidate with max-age=0
- no-store
- Client shouldn't cache anything at all (neither response contents nor any part of the actual request)
- no-transform
- Intermediate caches should not play with the content, say type guessing and encoding it to difference formats to save space.
- proxy-revalidate
- Same as must-revalidate but for intermediate caches
- Validate each user only once between the intermediate cache and user agent, but each new user should revalidate back to the origin
A client should revalidate if showing a twitter feed, but same client must revalidate when doing a purchase.
- Specifies an absolute GMT Date time as expiration value
- Specification suggest to not set a value more than one year into future
- Recommended to be used for static content while Cache-Control being opted for content which may have dynamic fragments (like css, js, xml, etc) fragments.
- Allows intermediate caches to store different versions of a url based on the fields specified.
- Assume that intermediate caches use a kv store to persist caches then these fields become part of the key.
- A common example would be to do
Vary: Accept-Encoding- Bad because not all browsers send same Accept-Encoding header for same type of response.
- Generally we just want to save 2 versions of a response e.g. compressed and uncompressed.
- It would be better to deal with this at gateway proxy with string matching against gzip/deflate instead.
- Or to save different versions by user-agent:
Vary: User-Agentif different kind of styles and scripts are loaded depending on the user agent.- This is also horrible. There are lots of different user-agents. Usually we just want 2 versions e.g. Mobile and desktop.
- We should probably even do this. Why? Responsive Design.
- Or slice by Referrer to show a welcome message in a popup:
Vary: Referrer- Also horrible.
- Say if your content is popular and linked by many sites and indexes by google (where each google result is a unique referrer) then it'd bloat cache.
- A better way would be for the gateway cache to save just 2 copies, one for external links and one for internal.
- Or
Vary: Acceptif responding with different response type(html, json, xml, yml, etc) depending on what client requests. Vary: *is horrible. UseCache-Control: privateinstead.Vary: Accept-Encoding, User-Agent, Cookie, Referer. Don't even get me started on this one.
- Legacy
pragma: no-cachereplaced byCache-Control: no-cache
- Fully qualified urls to retrieve fragments of page.
- Each fragment can then have its own set of cache rules, completely independent of the page that references it.
- Gateway deals fragments as separate items and hence caches them separately.
- For each incoming request gateway does following
- Check if a suitable version exists in cache, if so, pull that up or fetches one from backend.
- If the page has any ESI, those are treated in same way
- Once all fragements are available, gateway merges them together into page and sends back the compiled response.
- The whole check-or-fetch-merge-compile-send operation is done at gateway level and is transparent to application.
- Application only needs to
- Define ESI fragements
- Ensure those fragments are available under specified urls
- Use
s-maxageinstead ofmax-ageas browser is provided with fully compiled resource. Ifmax-ageis set browser will cache the compiled page and we don't want that.
- ETag is strong validator while Last-Modified is weak (default, server may change that)
- RFC2616 recommends that a client must send ETag for any cache conditionals
- In the case where both are provided, both are used.
- Act as if no cache-canditionals were specified, compile the whole response as a normal request.
- Browser Developer Tools
- curl
- Charles Proxy
- Hurl.it