What Is the `Cache-Control` Header?

What Is the `Cache-Control` Header?

Master the Cache-Control header to improve web performance. Learn directives like max-age, public/private, no-cache, and immutable for faster apps.

If you're building anything for the web-APIs, SPAs, static sites-your performance heavily depends on proper caching. The Cache-Control header is the core of HTTP caching. It tells browsers, CDNs, and reverse proxies exactly how to cache your response.

Let’s break it down without the noise.


What Does Cache-Control Do?

It defines caching rules:

  • how long something can stay cached
  • who can cache it
  • whether it requires revalidation
  • whether it’s allowed to be stored at all

You attach it to your response like this:

Cache-Control: max-age=3600, public

This says: “Cache this for 1 hour. Anyone can store it.”


Common Cache-Control Directives

1. max-age

How long (in seconds) the resource should be cached.

Cache-Control: max-age=86400

1 day.


2. public vs private

  • public: CDNs, proxies, browsers - everyone can cache.
  • private: Only the user’s browser can cache it. Use it for anything tied to a specific user.

Example:

Cache-Control: private, max-age=600

3. no-cache

The content can be cached, but must be revalidated before use.

Cache-Control: no-cache

It’s misleading. It doesn’t block caching. It blocks using the cached version without checking with the server.


4. no-store

The nuclear option.

Cache-Control: no-store

Nothing is cached. Useful for:

  • payment pages
  • personal data
  • login tokens
  • dashboards

5. must-revalidate

Forces the cache to revalidate when expired.

Cache-Control: max-age=0, must-revalidate

Good for data that must always be fresh.


6. immutable

For assets that never change.

Cache-Control: max-age=31536000, immutable

Tells the browser: “Don’t even try revalidating. This file will never change.”

Perfect for:

  • hashed JS bundles
  • images with versioned filenames

Best Practices

Static Assets (JS, CSS, images)

If you use hashed filenames:

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

Fastest possible web experience.


API Responses

Most APIs shouldn’t be cached globally:

Cache-Control: private, max-age=0, no-cache

For public APIs (weather, news, etc.):

Cache-Control: public, max-age=60

HTML Pages

If content changes often:

Cache-Control: no-cache

SPAs with versioned assets:

Cache-Control: no-cache, must-revalidate

Examples

Express.js

app.get("/api/data", (req, res) => {
  res.set("Cache-Control", "private, max-age=0, no-cache");
  res.json({ ok: true });
});

Nginx

location /static/ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

Go

w.Header().Set("Cache-Control", "public, max-age=60")

Why Cache-Control Matters

  • Faster page loads
  • Lower server load
  • Cheaper CDN bills
  • Better SEO (Core Web Vitals)
  • Avoids stale or incorrect content

Caching is easy to ignore but painful to fix when misconfigured.


Conclusion

Cache-Control gives you fine-grained control over how your app is cached across the web. Use it well, and your site becomes fast, cheap, and stable. Use it badly, and you'll serve stale HTML or hammer your servers for no reason.


Album of the blog: