The way it works is a cache is placed at client side (browser), proxy server or the reverse proxy server, which can be used to achieve lower response times. Overall load and bandwidth utilization at the server can hugely improve with the use of caches.
Whenever a client requests a resource, it first goes to the cache.
- If the cache is able to provide the requested resource, then we call it a cache HIT.
- If the cache is NOT able to provide the resource either due to its unavailability or if the resource has expired, we call it a cache MISS.
Some HTTP headers have been formulated to determine how the caching for a resource will be done -
We have some pre-HTTP1.1 cache headers which are still supported, but are not being used -
- Expires - It contains the absolute time of the moment, the resource will be termed stale or expired.
- Pragma - It can contain only one value - no-cache, which is used when certain resource shouldn’t be cached.
In HTTP1.1, we got a new header - cache-control which comes along with many directives -
- private - It means that the content can be cached only at the client side (browser).
- public - It means that the content can be cached at public locations, mainly the proxies.
- max-age - It conveys the maximum number of seconds a content can be kept in a cache.
- no-store - It means that the content can not be stored in a cache.
- no-cache - It means that the content can be cached but in order for client to reuse it, the client must validate itself mostly via Etag directive.
In the event, we get value like cache-control: max-age=3600, public
, it means that the content can be cached at public places for maximum of 3600 seconds.
In the event, we get value like cache-control: max-age=3600, private
, it means that the content can be cached at the client side only for maximum of 3600 seconds.
- s-max-age - ‘s’ stands for shared. In a situation wherein we see a header like -
cache-control: max-age:600, s-max-age:3600
, it would mean the content can stay for 600 seconds on the client, and for 3600 seconds on the shared public spaces. - must-revalidate - Sometimes, whenever there is any network issue, or the server is down, the client can serve you the stale data if when max-age has expired. To override it, we specify must-revalidate which specifies that the client should not serve the stale content and must get the good content from the server.
- proxy-revalidate - It’s the same behavior as must-revalidate but with proxies. But here in this case, the client can serve the stale content to the user, but if it reaches a proxy, they can’t serve stale content to the client.
Directives can be mixed like this - Cache-control: max-age=300, s-max-age=3600, public, must-revalidate
.
Cache Validation
Etag and If-None-Match
ETag is usually used by the server to send along a unique identifier for the resource which was sent to the client. Lets say if server had responded with an image, and these headers -
Cache-control: max-age=3600, public;
Etag: "2uh878fbghfd89fvfd";
& lets consider if client sends back another header - If-None-Match, and passes along same Etag in the header like - If-None-Match: "2uh878fbghfd89fvfd"
, it would mean
- The client will keep on using the same image for 3600 seconds, and then check with cache for the new resource.
- If cache found a new resource with a different Etag from the server to serve the client, it will send the new resource along with a new Etag.
- If the cache has got a new resource with the same Etag, then cache will send a 304 response code which means Not modified, and the client will keep on using the same resource for another 3600 seconds.
We can have weak Etags as well, which are prefixed by a W, which necessarily means that 2 resources with same Etag might not be fully same.
Last-Modified and If-Modified-Since
Last-Modified header contains the timestamp of the moment the resource was last modified. The logic is same as that of Etag.
- If the client has sent a timestamp in the request as the value for If-Modified-Since header, the cache will check the newly obtained resource.
- If the cache finds a new resource which has been modified since the value obtained in If-Modified-Since header, then the cache will return the new response, along with the Last-Modified header.
- If the cache is not able to find a new resource which has been modified since, then it will return 304 which means Not Modified, and the client will refresh the cache.