Glossary
Cache-Control Header

Cache-Control Header

Alex Khazanovich

If your website feels slow, outdated, or inconsistent for users across visits, there's a good chance your caching strategy needs help. And at the heart of that strategy sits one powerful tool: the Cache-Control header.

This isn’t some obscure setting only engineers touch. If you're running a site, delivering content, or working on performance, you will likely use this header - a lot.

What Is the Cache-Control Header?

The Cache-Control header is an HTTP header that tells browsers and intermediate caches (like CDNs or proxies) how to cache your content. Think of it like a set of instructions: “Keep this for 10 minutes,” or “Don’t ever store this,” or “You can reuse this, but check with me first.”

You’ll find it in both HTTP responses (sent from the server to the client) and HTTP requests (sent from the client to the server). Each has its purpose, but the response header is what most websites use to manage how content is stored and reused.

Why You Should Care About HTTP Header Cache-Control

Speed. Consistency. Bandwidth savings.

If your site reloads the same images, stylesheets, or scripts every time someone clicks a link, you’re not caching right. The Cache-Control header helps you fix that. It decides what should be stored locally, for how long, and under what conditions.

When you configure this header properly:

  • Your pages load faster
  • You reduce server load
  • Your bandwidth bill shrinks
  • You avoid showing users outdated or incorrect data

That’s a big win across the board, for SEO, user experience, and even your infrastructure costs.

‍{{cool-component}}‍

Key Directives in the Cache-Control Response Header

Here’s a breakdown of the most common cache-control response directives:

Directive What It Does
max-age=seconds Content is fresh for this number of seconds
no-cache Content can be stored but must be revalidated before use
no-store Content should not be stored at all
public Content can be cached by any cache (including shared caches like CDNs)
private Content is only for the browser, not shared caches
must-revalidate Must revalidate content when it becomes stale
s-maxage=seconds Like max-age, but for shared (CDN/proxy) caches only

These aren’t meant to be used in isolation. You’ll often combine them to control behavior precisely.

Example:

Cache-Control: public, max-age=3600, must-revalidate

This says: any cache can store it, it’s fresh for an hour, but once stale, check before reuse.

Cache-Control Request Header is How the Client Makes Demands

The browser can also send its own Cache-Control request header when asking for a resource.

For example:

  • no-cache: “I want this file, but don’t serve me a cached copy. Check with the server first.”
  • max-age=0: “Only give me a cached copy if it’s brand new.”

This is useful when users click “refresh” or when scripts force revalidation behind the scenes.

You don’t set these as a site owner, but understanding them helps you diagnose weird caching behavior or debug issues in dev tools.

Cache-Control Header Best Practices

Now let’s walk through what you should be doing when setting this header.

1. Set Long Cache Times for Static Assets

Your images, CSS files, JS bundles change rarely. Tell the browser to keep them for a long time.

Example:

Cache-Control: public, max-age=31536000, immutable

This caches the file for a year and tells the browser, “Don’t bother checking if it changed.”

Tip: Use fingerprinting (e.g. main.49f3.js) so you can change file names when content changes.

2. Avoid Caching Dynamic or Personalized Content

If you're serving user-specific dashboards, account pages, or personalized search results, you do not want those cached globally.

Example:

Cache-Control: private, no-cache, no-store, must-revalidate

This forces the browser to always fetch a fresh version and ensures proxies don’t serve one user’s data to another.

3. Control CDN Caching Separately Using s-maxage

CDNs like Cloudflare or Akamai are shared caches. Sometimes, you want them to hold onto content longer than the user’s browser.

Example:

Cache-Control: public, max-age=60, s-maxage=600

This keeps the browser version fresh for 1 minute but lets the CDN hold onto it for 10.

4. Combine Headers Intelligently

Here’s what a smart setup might look like for a marketing page:

Cache-Control: public, max-age=3600, must-revalidate

And for your login endpoint:

Cache-Control: private, no-store

You want the browser to never store sensitive POST results, but happily cache your background illustrations for a month.

Common Mistakes to Avoid

  • Relying on default behavior: Without explicit headers, you leave caching up to guesswork.
  • Using no-cache when you meant no-store: no-cache still allows storing; it just requires revalidation.
  • Not fingerprinting static assets: If you don’t rename files when content changes, long-term caching will betray you.

Diagnosing Cache-Control Issues

You can inspect the Cache-Control header using browser dev tools (Network tab). Check the response headers to see what’s being sent.

Also, use online tools like web.dev or Google PageSpeed Insights to check if your assets are being properly cached.

‍{{cool-component}}‍

How Cache-Control Works with Other Headers

Caching doesn’t rely on cache-control alone. It often works alongside other HTTP headers, like:

  • ETag: A version identifier that lets the browser ask, “Is this version still good?” If yes, the server can respond with 304 Not Modified.
  • Expires: An older HTTP/1.0 header. Still works, but cache-control overrides it.
  • Last-Modified: A timestamp for when the content was last changed.

If your CDN, browser, or server sees conflicting headers, cache-control usually wins, but not always. You don’t need to remove Expires, but make sure it agrees with your cache-control logic.

When Should You Skip Caching Entirely?

Not everything benefits from caching. Skip it when:

  • You’re dealing with payment flows or checkout pages
  • Serving temporary authentication tokens
  • Sending user-specific data that must never be shared

Use this:

Cache-Control: no-store

This tells every system (browser, proxy, CDN) not to save the data anywhere. It's the strictest level of no-cache.

‍{{cool-component}}‍

Conclusion

The cache-control header is small but mighty. It shapes how the web delivers your content, from first visit to returning user.

So next time you push a new feature, image, or layout tweak, remember this: how you cache it will decide how fast users see it.

Published on:
June 16, 2025

Related Glossary

See All Terms
This is some text inside of a div block.