Does Cache-Control: s-maxage=31536000 guarantee no revalidation by intermediaries (CDN, proxies)?

I am trying to optimize the caching of versioned static files (e.g., style.abc123.css) served through a CDN or proxy cache. I am currently using the following HTTP header:

Cache-Control: s-maxage=31536000

My understanding is that this directive tells shared caches (like CDNs or proxies) to serve the cached resource for up to one year (31536000 seconds) without revalidating it with the origin server.

However, I have a couple of questions:

  1. Does s-maxage=31536000 alone guarantee that no conditional revalidation (e.g., via If-Modified-Since or If-None-Match) will occur during this period, even if a client forces a refresh or revalidation?
  2. If not, is it necessary to add the immutable directive (e.g., Cache-Control: s-maxage=31536000, immutable) to ensure that no revalidation happens at all?

I would appreciate clarification on this behavior to ensure I am correctly optimizing caching for these static resources.

Thank you in advance!

It was difficult to debug this. Most articles recommend adding immutable, but I don’t understand the rationale behind it.

You’re on the right track in optimizing caching for versioned static files! Let’s clarify the behavior of s-maxage and the role of immutable so you can ensure efficient caching without unnecessary revalidation.


1. Does s-maxage=31536000 alone guarantee no revalidation during this period?

Short Answer: Not entirely, especially for client behavior.

Explanation:

  • The s-maxage=31536000 directive instructs shared caches (like CDNs or proxies) to serve the cached resource for up to one year without revalidating it with the origin server. This generally works as expected in shared environments.
  • However, client-side caches (like browser caches) don’t honor s-maxage; they look at max-age instead. If the browser cache decides to revalidate (e.g., due to a forced refresh), it might send a conditional request (If-Modified-Since or If-None-Match) to the CDN or proxy, which can then trigger a revalidation with the origin if not prevented.

2. Is immutable necessary to prevent all revalidation?

Short Answer: Yes, adding immutable strengthens the cache behavior by preventing revalidation entirely for the specified duration.

Explanation:

  • The immutable directive indicates that the resource will never change during its cache lifetime (as specified by s-maxage or max-age).
  • Without immutable, clients or shared caches may still revalidate the resource under certain conditions, such as:
    • A user forcing a refresh in the browser.
    • Some intermediary cache misinterpreting a conditional request.
  • With immutable, even a client-side “hard refresh” won’t trigger revalidation because the browser understands that the resource doesn’t need revalidation.

Rationale for Using immutable

When you use versioned static files (e.g., style.abc123.css), the file name changes whenever the content changes. This makes revalidation unnecessary, as any updates to the file would use a different name. Adding immutable ensures that:

  • Browsers and CDNs fully trust the cache and never revalidate until the s-maxage or max-age duration expires.
  • Conditional requests (If-Modified-Since or If-None-Match) are completely avoided, improving performance.

Recommended Cache-Control Header for Versioned Static Files

For versioned static files, the following header ensures optimal caching:

Cache-Control: s-maxage=31536000, max-age=31536000, immutable
  • s-maxage=31536000: Caches the resource in shared caches (like CDNs) for one year.
  • max-age=31536000: Caches the resource in client-side caches for one year.
  • immutable: Prevents any revalidation requests during the cache lifetime.

Debugging and Verification Tips

  1. Test with a forced refresh:
  • Use developer tools in the browser (e.g., Chrome DevTools) and reload the page with Ctrl+Shift+R or Cmd+Shift+R. Observe if the browser sends a revalidation request. With immutable, this should not happen.
  1. Use online tools to inspect headers:
  • Test your static resources with tools like RedBot or Pingdom to verify caching headers.
  1. Analyze CDN behavior:
  • If using a CDN, confirm that it respects s-maxage and does not revalidate unnecessarily.

Why Articles Recommend immutable

Many articles emphasize immutable because:

  • It provides an extra layer of assurance that revalidation won’t occur, even under edge cases.
  • It’s particularly useful for versioned resources, where the resource name guarantees uniqueness, making revalidation redundant.

Using immutable ensures the most efficient caching behavior and avoids performance pitfalls caused by unnecessary revalidation requests.