blatantly copypasted from https://httptoolkit.tech/blog/http-wtf/
No-cache means “do cache”
Caching has never been easy, but HTTP cache headers can be particularly confusing. The worst examples of this are
private. What does the below response header do?
Cache-Control: private, no-cache
It looks like this means “don’t store this response anywhere”, right?
In reality, this means “please store this response in all browser caches, but revalidate it when using it”. In fact, this makes responses more cacheable, because this applies even to responses that wouldn’t normally be cacheable by default.
no-cache means that your content is explicitly cacheable, but whenever a browser or CDN wants to use it, they should send a request using
If-Modified-Since to ask the server whether the cache is still up to date first. Meanwhile
private means that this content is cacheable, but only in end-client browsers, not CDNs or proxies.
If you were trying to disable caching because the response contains security or privacy sensitive data that shouldn’t be stored elsewhere, you’re now in big trouble. In reality, you probably wanted
If you send a response including a
Cache-Control: no-store header, nobody will ever cache the response, and it’ll come fresh from the server every time. The only edge case is if you send that when a client already has a cached response, which this won’t remove. If you want to do that and clear existing caches too, add
Twitter notably hit this issue. They used
Pragma: no-cache (a legacy version of the same header) when they should have used
Cache-Control: no-store, and accidentally persisted every user’s private direct messages in their browser caches. That’s not a big problem on your own computer, but if you share a computer or you use Twitter on a public computer somewhere, you’ve now left all your private messages conveniently unencrypted & readable on the hard drive. Oops.