Reference guide · cloudflare · Published 2026-08-16 · 4 min read
Cloudflare cache TTL tuning with Cache-Control
Tune Cloudflare edge cache TTL: Cache-Control directives, s-maxage vs max-age, default TTLs, and Cache Rules to set caching duration.
- ·What makes Cloudflare cache
- ·TTL defaults
- ·Set the right TTL
What makes Cloudflare cache a response
Cloudflare is a shared (edge) cache in front of your origin. Whether a response is cached, and for how long, depends on three things: the origin Cache-Control and Expires headers, Cloudflare's zone defaults, and any cache rules that override both.
The directive Cloudflare reads first is s-maxage, because by definition s-maxage overrides max-age for shared caches. A response like Cache-Control: public, max-age=300, s-maxage=3600 tells browsers to keep it for 5 minutes and Cloudflare for an hour. If there is no s-maxage, Cloudflare falls back to max-age, and if there is no Cache-Control at all, it applies its own default edge TTL.
Origin Cache Control
By default, Free, Pro and Business zones have Origin Cache Control enabled. That is the toggle that tells Cloudflare to strictly respect the origin's Cache-Control directives. When the feature is enabled, private, no-store, no-cache and max-age=0 responses are not cached, and a public response with a positive max-age is cached as directed.
When Origin Cache Control is disabled, Cloudflare instead relies on its zone defaults, which can cache responses even without usable origin headers (all cookies, query strings and dynamic look-alike paths considered). For most sites, leaving Origin Cache Control enabled is the predictable, honest setup, and it matches what the HTTP caching guide describes for any CDN.
The TTL defaults
If the origin sends no usable Cache-Control or Expires, Cloudflare uses this default edge TTL:
| Response code | Default edge TTL |
|---|---|
| 200, 206, 301 | 2 hours |
| 302, 303 | 20 minutes |
| 404, 410 | a few minutes |
| other codes | not cached by default |
You can see which bucket your page fell into with the cf-cache-status response header. The statuses that matter: HIT (served from edge cache), MISS (fetched from origin this time, now cached if eligible), REVALIDATED (edge had a stale copy and validated it against the origin), and DYNAMIC or BYPASS (not cacheable in this setup; for example an HTML page carrying cookies, or an origin no-cache). If you see DYNAMIC on a URL you expected cached, the cache key decision lives in the rules below, not in the header itself.
Setting the right TTL with cache rules
Tuning begins at the origin headers, since they travel with the file; set sensible max-age and s-maxage there first. When the origin returns the wrong header, or the CDN needs different rules per path, use the Cache Rules product under Rules > Cache Rules:
- "Use Cache-Control if present" respects the origin when you send a header, and applies Cloudflare defaults otherwise. This is the default mode and the safest.
- "Ignore Cache-Control and use a TTL" overrides anything your origin says. Use it only for a purpose where the origin is known wrong, such as an API pretending to be static.
- Status code TTL attaches a TTL to a status response: e.g. a short 1-minute retention for 429 from the origin. It silences cache runaway.
For static, versioned assets (CSS/JS bundles with a hash), a long edge TTL of one year plus cache-busting is the standard pattern. For HTML, keep it short, typically 0 to a few minutes, or use no-cache so the browser revalidates the document while caching sub-resources. The browser cache error page covers what stale HTML does to users before the origin headers change.
Tuning without breaking fresh content
- Keep per-page HTML out of long TTLs: cache the assets, not the shell.
- Use
s-maxageto separate the browser TTL (max-age) from the edge TTL so visitors revalidate often while the CDN tolerates a longer holding period. - Watch
cf-cache-status: BYPASSwhen a rule says "Cache Everything" but a cookie exists. Cache Rules expose the same public/private logic as Page Rules used to, which is why the cache rules tuning article treats that path. - Purge the cache only when the TTL itself is the problem: the purge guide covers the three purge scopes, and a wrong TTL in cache rules is usually cheaper to fix by updating the rule than by clearing the cache.
Prevention
Set measured cache lifetimes as a default, not an exception. Long-lived assets, short-lived documents, and a clearly tested s-maxage are the habit that keeps a Cloudflare cache fast without leaving visitors on stale pages.