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.

Flat editorial illustration showing a planetary shield with concentric orbit rings, one radial segment glowing as a small request dot climbs.
Illustration: this article at a glance.

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.

Editorial close-up illustration showing a planetary shield with concentric orbit rings, one radial segment glowing as a small request dot settles.
Illustration: a closer look at the technique described above.

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 codeDefault edge TTL
200, 206, 3012 hours
302, 30320 minutes
404, 410a few minutes
other codesnot 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:

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

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.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services