What happens when you use Cache-Control: max-age with ETags?

Viewed 836

There are several similar questions, but none of the ones I've found are clear or definitive.

Here's the behavior I want:

  • As long as the network is available, the browser must check if there's a new version
  • If there isn't a new version, the browser can use the cached version
  • The cached version expires after X days

I think I can do this with Cache-Control: max-age and ETags. However, I can't find whether the max-age should be 0 or how long the content should be cached for.

E.g. if I do Cache-Control: max-age=86400 (1 day) with an ETag, would it:

  1. Make a server request every time, but the server will just return 304 if the ETag didn't change. After 1 day, discard the cached version, and refetch from the server (which should be the same as the discarded version).

  2. Doesn't make any server requests for a day. Then, after 1 day, the server can still return 304. The cached version can stay indefinitely.

I'd like the browser to refetch after X days because in case there's a bug, I don't want users stuck with a broken cached version.

1 Answers

Here's the behavior I want:

  • As long as the network is available, the browser must check if there's a new version
  • If there isn't a new version, the browser can use the cached version

This is a common use case, and can be accomplished by using Cache-Control: no-cache (or max-age=0, must-revalidate) and providing an ETag or Last-Modified header.

  • The cached version expires after X days

This is not possible. It's not part of the design of HTTP caching because there's no use case for it.

I'd like the browser to refetch after X days because in case there's a bug, I don't want users stuck with a broken cached version.

If the browser is checking for a new version each time, how can the user ever get stuck with a "broken" cached version?

If I do Cache-Control: max-age=86400 (1 day) with an ETag, would it:

  1. Make a server request every time, but the server will just return 304 if the ETag didn't change. After 1 day, discard the cached version, and refetch from the server (which should be the same as the discarded version).

  2. Doesn't make any server requests for a day. Then, after 1 day, the server can still return 304. The cached version can stay indefinitely.

Number 2. The max-age tells the browser how long it can consider the resource to be fresh, meaning that the cached version can be used without checking with the server. When that time has expired, the resource is considered stale, and a new request has to be made. If the cached resource has an ETag or Last Modified header that request can be a conditional one to allow the server to avoid sending the entire resource in the response.

Related