HTTP Cache-Control Header Generator: Cache the Right Way for Each Resource
Cache-Control directives interact in non-obvious ways — no-store silently makes max-age irrelevant, no-cache and immutable directly contradict each other, and public vs. private determines whether a shared CDN cache is even allowed to store the response at all. This generator builds correct headers from presets for common resource types, or from individual directives with warnings for contradictory combinations.
no-store disables caching entirely, overriding every other directive.
Matching Cache Strategy to Resource Type
A fingerprinted static asset (app.a1b2c3.js) can be cached for a year with immutable, since a content change produces a new URL entirely. An HTML page that might change between visits needs no-cache to force a freshness check each time. An authenticated API response often needs no-store entirely, since caching it — even briefly, even privately — can leak stale or sensitive data.
public vs. private: Who's Allowed to Cache
public allows any cache in the chain — your browser, a CDN, a corporate proxy — to store and reuse the response for any user. private restricts caching to the requesting browser only, which matters when the response contains data specific to one authenticated user that shouldn't be served to someone else from a shared cache.
max-age vs. s-maxage: Browser vs. Shared Cache
max-age is the default freshness lifetime respected by all caches. s-maxage overrides it specifically for shared caches (CDNs, reverse proxies) — a common pattern is a short max-age (so browsers revalidate often) paired with a longer s-maxage (so your CDN absorbs most traffic and only hits your origin occasionally).
Practical Examples
A Fingerprinted JS Bundle
Cache forever, no revalidation needed.
- 1.Cache-Control: public, max-age=31536000, immutable
- 2.Browser never re-checks — the URL itself changes on update
A Logged-In User's Dashboard Data
Sensitive, per-user data.
- 1.Cache-Control: no-store
- 2.Every request goes to the server, nothing is cached anywhere
Directives This Generator Covers
- public / private / no-store
- max-age and s-maxage
- no-cache: cache but always revalidate
- must-revalidate: don't serve stale on error
- immutable: skip revalidation entirely
Good Use Cases
- Setting correct caching for static assets vs. API responses
- Debugging why a CDN is (or isn't) caching a resource
- Avoiding accidental caching of sensitive per-user data
- Learning how max-age and s-maxage interact with CDNs
Frequently Asked Questions
What's the difference between no-cache and no-store?
no-cache allows the response to be cached, but forces revalidation with the server before each use — the cached copy can still be used if the server confirms it's still fresh. no-store forbids caching entirely; nothing is stored, and every request goes fully to the server.
What's the difference between max-age and s-maxage?
max-age applies to all caches, including private browser caches. s-maxage applies only to shared caches (CDNs, reverse proxies) and overrides max-age for those specifically — useful when you want a CDN to cache longer (or shorter) than an individual browser should.
What does immutable actually do?
It tells the browser the resource will never change for the duration it's considered fresh, so there's no need to even check for updates on a page reload (not just avoid re-downloading, but skip the revalidation request entirely). It's ideal for versioned/fingerprinted static assets (like app.a1b2c3.js) that get a new URL whenever their content changes.
Why use public vs. private?
public allows any cache — including shared ones like CDNs and ISP proxies — to store the response. private restricts caching to the end user's own browser, appropriate for responses containing user-specific data that shouldn't be shared across users via an intermediate cache.
When should I use the 'API Response (no caching)' preset?
For endpoints returning dynamic, request-specific, or sensitive data where every request should reach your server fresh — authentication endpoints, real-time data, or any response where stale data would cause incorrect behavior.
Why does the tool warn about no-store with max-age set?
no-store instructs caches not to store the response at all, which makes any max-age or s-maxage value irrelevant — there's nothing to keep fresh if it was never stored in the first place. The warning catches this contradictory combination before you ship it.