Skip to main content

Cache Response Rules: Fixing CDN Caching After Origin

Cache Response Rules: Fixing CDN Caching After Origin

CDNs can now rewrite the origin's response before it's cached. Learn how response-phase cache rules fix Set-Cookie, ETag, and Cache-Control problems without touching origin code.

CDNs can now rewrite the origin's response before it's cached. Learn how response-phase cache rules fix Set-Cookie, ETag, and Cache-Control problems without touching origin code.

When people talk about tuning a CDN's cache behavior, the conversation usually starts and ends at request time: which resources get cached, which cache key applies, which TTL to use. All of that gets decided the moment a request hits the edge, before it even reaches the origin. But in practice, what actually determines cacheability is often the origin server itself — the Set-Cookie, Cache-Control, and ETag headers it happens to return. And those headers are frequently wrong, incomplete, or overly defensive, simply because they're a framework's default behavior rather than a deliberate decision anyone made.

Cloudflare's Cache Response Rules, announced in July 2026, fills exactly that gap: a distinct processing phase that runs after the origin has responded but before Cloudflare writes the content into cache. This piece looks at the concrete problem it solves, how the architecture is structured, and how web teams can put it to use today.

Why Request-Time Rules Aren't Enough

Most CDN caching logic lives in "request phase" rules: look at the URL pattern, the path, or a header, and decide whether to cache. But that decision is made independently of what the origin actually returns. In practice, teams run into the same handful of problems again and again:

  • Set-Cookie leaking onto static assets — a framework adds a session cookie to every response by default, and that habit bleeds into fully static files like .js, .css, or .woff2. CDNs, for good reason, avoid caching responses that carry Set-Cookie.
  • Overly cautious Cache-Control: no-cache — framework defaults tend to favor "safe by default," which means content that should be cacheable gets forced into revalidation anyway.
  • Misconfigured ETag/Last-Modified — build pipelines that regenerate an ETag on every deploy, even when the underlying content hasn't changed, generate needless revalidation traffic.
  • Origin and CDN owned by different teams — in most mid-to-large organizations, changing origin code means routing through another team's review, deploy pipeline, and risk sign-off. Even a one-line header fix can take weeks.

That left teams with three unsatisfying options: change the origin code (slow, risky, often outside your control), write a custom Worker or edge function to rewrite responses (extra maintenance, extra latency), or simply accept a lower cache hit ratio (a direct hit to performance and cost). None of these is a real solution.

The Response Phase: Deciding After the Origin, Before the Cache

Cache Response Rules splits cache decision logic into two distinct phases:

  • Cache Rules (Request Phase) — runs before the request reaches the origin; decides whether something is cacheable, which cache key to use, and the baseline cache parameters.
  • Cache Response Rules (Response Phase) — runs after the origin response is received but immediately before it's written to Cloudflare's cache; adjusts how caching behaves at the header level.

When the two phases conflict, the response-phase rule wins — a header coming from the origin can be stripped or altered in the response phase even if a request-phase rule already made an assumption about it. That moves cache logic from a "predict ahead of time" model to a "correct after seeing the real response" model.

Aspect Cache Rules (Request Phase) Cache Response Rules (Response Phase)
When it runs Before the origin is reached After the origin response, before it's cached
What it decides Cacheability, cache key, baseline parameters Header stripping, cache tags, Cache-Control rewriting
Input source Request URL, path, headers The origin's actual response headers
On conflict Loses Wins

The response phase offers three core capabilities. First, header stripping: problematic headers such as Set-Cookie, ETag, or Last-Modified can be removed before cache evaluation happens — with zero changes to origin code, responses that would otherwise be uncacheable become cacheable. Second, cache tag management: tags can be added, removed, or set using static values or dynamic expressions that parse response headers, such as split(http.response.headers["Surrogate-Keys"][0], ",", 64)— particularly useful for teams migrating off a legacy CDN who need to translate vendor-specific tag formats on the fly. Third, Cache-Control directive rewriting: duration directives (max-age, s-maxage, stale-if-error, stale-while-revalidate), qualifying directives (private, no-cache), and boolean directives (no-store, must-revalidate, public, immutable) can all be edited directly.

The most practically useful detail here is the cloudflare_only parameter: it lets you apply a directive change only to Cloudflare's own cache behavior, leaving what the browser sees untouched. That makes it possible to run genuinely separate policies — a long cache life at the edge, a shorter one in the browser.

Practical Scenarios: What This Buys You Today

The most common use case is static asset optimization: for known file extensions like .js, .css, or .woff2, strip the Set-Cookieheader before cache evaluation, with zero origin changes, so those assets become cacheable. A second common pattern is split cache lifetimes: cache an asset at the edge for 30 days (s-maxage: set 2592000, cloudflare_only=true) while showing the browser only a 1-day TTL (max-age: set 86400, cloudflare_only=false) — the origin avoids unnecessary repeat requests while the browser still keeps a reasonable revalidation rhythm.

A third use case is deliberately overriding a framework's default no-cache directive on known-safe paths, such as /static/*. A fourth is CDN migration: an old CDN's proprietary cache-tag header format can be translated in real time into the new system's Cache-Tag format using a dynamic expression, instantly enabling tag-based purge functionality without touching origin code at all.

Configuration is available both from the dashboard ("Create rule" → "Cache Response Rule") and via API/Terraform, with no plan restriction — rules can be tested in draft mode before being switched live.

Conclusion: Fixing Header Problems Without Touching Origin

Response-phase cache control fits a broader architectural pattern: moving decision points to the moment when the information needed to make that decision is actually available. The most accurate signal for a cacheability decision is the origin's real response — anything decided before seeing that response is, by definition, a guess. For teams that adopt this approach, the practical payoff is concrete: without waiting on the origin team and without writing a custom Worker, a handful of rules at the cache layer can raise hit ratios, cut unnecessary revalidation traffic, and speed up CDN migrations.