Cache invalidation is the first hard problem in computer science. In this post I discuss some ways handle it in the context of HTTP.
Often stale data is okay. In the comment section of a blog, it probably does not
matter if comments posted within the last hour are not visible to all users. An
origin server can specify this with the
Expires HTTP headers.
But there are some cases where this does not hold:
- If a user logs in or out the interface must immediately reflect this.
- If a user posts a comment, they must see the result.
The origin server has some options within HTTP to force proxies and browsers to invalidate parts of their cache on these events. The following headers may be userful.
Invalidate caches when cookies change. Thus, if the session cookie changes, the
interface will be updated. When using this, make sure to set
private for logged in users to avoid thrashing shared caches with user-specific
pages. Also keep in mind that a malicous user can still thrash caches by setting
unique irrelevant cookies. This can be avoided by responding with
Cache-Control: private for all request with the
Cookie header (regardless of
Unfortunately, this prevents shared caching if using some tracking cookie for analytics as all users will have a unique cookie regardless of being logged in or not.
A fastly blog post discourges the use of this header, saying that “
probably one of the most unique request headers, and is therefore very bad [in
Vary]”. However, that disregards the importance of browser caches.
When responding to a form POST with a 303 See Other response, the redirect target will be invalidated. For instance if using a plain form for posting comments and then redirecting back to the page that shows comments1. In these cases we get correct cache behavior “for free”.
When responding to a POST, the URI in the
Content-Location header will be
invalidated. This is useful if comments are posted through AJAX (thus without a
redirect) and the corresponding GET endpoint must be invalidated.
All this information is available in the HTTP specification. I recommend starting with section 13 on caching.