Article summary — original

Cloudflare Launches Cache Response Rules to Modify Origin Headers Before Caching Cloudflare has introduced Cache Response Rules across all plans, providing a rule type that operates after an origin server responds but before content is written to the edge cache. Cache Response Rules evaluate after an origin server replies, enabling header modifications without origin code adjustments. The rules complement existing request-phase Cache Rules by adjusting whether and how content is cached, though they cannot change the cache key. Supported actions include stripping headers like Set-Cookie and ETag, setting or translating cache tags, and altering Cache-Control directives. A cloudflare_only option allows directives to control Cloudflare's edge caching while leaving the browser's downstream Cache-Control header untouched. Targeting Origin Response Flaws Cache efficiency often degrades when origin servers inadvertently attach headers such as Set-Cookie, no-cache directives, or aggressive ETags to cacheable static assets. Because these headers arrive in the response, traditional request-time rules cannot evaluate or alter them. Cache Response Rules execute after the origin responds but before Cloudflare writes the payload to its cache, allowing administrators to address origin header misconfigurations directly at the edge. Supported Actions The ruleset includes three core actions. The set_cache_settings action removes headers like Set-Cookie, ETag, or Last-Modified from both cacheable and dynamic responses, which can restore asset cacheability or toggle Smart Edge Revalidation. The set_cache_tags action defines static cache tags or parses existing response headers—such as translating comma-delimited Surrogate-Keys from other CDNs using a split function limited to 1–128 items—to enable fast tag-based purging. The set_cache_control action permits adding or removing directives including max-age, s-maxage, no-cache, and immutable. Edge Decoupling and Availability Using the cloudflare_only parameter on Cache-Control directives, users can dictate Cloudflare's edge cache retention duration independently from the directives delivered downstream to the client browser. Cache Response Rules do not replace request-based Cache Rules—which still establish the cache key and initial lookup behavior—and are currently available across all Cloudflare plan tiers.

Article summary — zh

Cloudflare 推出 Cache Response Rules 以在响应阶段优化缓存控制 Cloudflare 宣布推出 Cache Response Rules,该规则在源站返回响应后、写入缓存前执行,允许用户直接在边缘修改源站响应头,避免因源站配置问题导致资源无法被有效缓存。 在源站回复后、边缘写入缓存前生效,无需修改源站代码即可剥离阻碍缓存的头部或重写指令。 与请求阶段运行的 Cache Rules 形成互补,专注于在获取源站响应后决定“是否写入缓存”与“如何缓存”。 提供三大操作:剥离特定响应头(如 Set-Cookie)、配置或转换 Cache-Tag、以及修改 Cache-Control 指令(包含仅针对边缘生效的设置)。 解决响应阶段导致的缓存失效问题 CDN 缓存效率很大程度上受源站响应头控制。常见问题包括源站框架在静态资源上意外附加 Set-Cookie、返回过于激进的 ETag 导致重验证抖动,或返回仅适用于浏览器的 Cache-Control: no-cache 指令。由于这些头部只有在源站返回后才存在,请求阶段的规则无法感知并修改它们,导致原本可缓存的资源频繁回源,增加源站带宽与基础设施成本。Cache Response Rules 允许在边缘端直接拦截并修复这些问题。 与请求期 Cache Rules 的分工协作 Cache Rules 运行在请求阶段,依据 URL、请求头等参数决定是否查询缓存以及缓存键的选择。而 Cache Response Rules 运行在响应阶段,虽然不能更改已经确定的缓存键,但拥有对最终“是否缓存”和“如何缓存”的控制权。两者并非替代关系,而是分为两阶段协作,让用户可以在源站返回真实响应内容后拥有最终决定权。 三大核心操作与应用场景 该规则目前支持三种操作:一是 set_cache_settings,可剥离 Set-Cookie、ETag 或 Last-Modified 等标头以恢复资源的可缓存性;二是 set_cache_tags,允许静态添加或通过表达式解析源站响应头(如将旧 CDN 的 Surrogate-Keys 拆分转换为 Cloudflare 标签,上限支持 1 到 128 个元素);三是 set_cache_control,可修改 max-age 等指令,并支持开启 cloudflare_only 选项,使资源在 Cloudflare 边缘保持长期缓存的同时对浏览器保持独立的缓存时长。目前该功能已向所有套餐计划开放。

Saved original article

**Today we’re excited to announce Cache Response Rules.** These are a new rule type that runs after an origin server replies but before Cloudflare caches the content. If you've ever been irked watching something that should easily sail out of cache get dragged back to the origin by a stray `Set-Cookie` or wrong `Cache-Control`, headers that are sometimes hard or impossible to strip or change on the origin itself, then Cache Response Rules is that fix, applied at exactly the right moment. A CDN cache and an origin server work as a pair. Their goal is to answer from the cache whenever possible and only go back to the origin when the edge can’t respond. Every point of cache hit ratio comes from getting that division of labor right. Check the cache when we shouldn't, and we waste a lookup that was always going to miss. Check it too rarely, the origin serves traffic the edge should have absorbed, and the performance win evaporates. Importantly, the origin guides the cache. When it returns a cacheable asset, its response headers tell Cloudflare how long it’s OK to serve it, when and how to revalidate, and even whether to cache it at all. The cache is only ever as efficient as the origin allows. If the origin gets it wrong, cache becomes decoration while the origin infrastructure costs skyrocket. Most cache eligibility problems are not decided at request time. They manifest after the origin replies. A visitor asks for `/static/app.js`. Cloudflare checks cache, it misses, and forwards the request to the origin. The origin returns the file. Somewhere in those response headers, quietly, is a `Set-Cookie` header. The asset that should have been cached at every Cloudflare data center is now uncacheable. Multiply that by every visitor, on every site, with the same accidental header, and you have a cache hit ratio that is leaking origin bandwidth, ruining performance, and driving infrastructure costs higher. There is a long list of variations of this same problem. The origin sends `Cache-Control: no-cache` on assets that are perfectly safe to cache on the CDN. The origin sends correct directives, but they're meant for the browser, not for Cloudflare. Or the origin attaches an `ETag` (an identifier for a specific version of a resource) that's overly aggressive and causes revalidation thrash on every conditional request. Often, especially in large teams, those managing the origin’s responses and the group that manages the CDN are different. This makes changing a one-line header a weeks-long negotiation. None of these problems can be solved at request time. By the time Cloudflare sees the `Set-Cookie` on `/app.js`, the request phase is over. The response is already in flight. So we put a fix in the right place. **Cache Response Rules run after the origin’s response arrives at Cloudflare, but before it gets written to cache.** With them, you can rewrite `Cache-Control` directives, manage cache-tags, and strip headers like `Set-Cookie`, `ETag`, and `Last-Modified` from the origin response before Cloudflare's cache ever sees them. The fix lives entirely on Cloudflare. No origin code changes required. If you've used Cloudflare for any length of time, you've watched the cache control surface area evolve. A few years ago, most of this lived inside [Page Rules](https://developers.cloudflare.com/rules/page-rules/), which operated as a single, albeit overloaded, primitive that mixed caching with redirects, security, and a dozen other behaviors, all evaluated on requests. We later [split these rules apart](https://blog.cloudflare.com/future-of-page-rules/) so that only relevant behavior changes would be evaluated against requests, reducing unnecessary latency and allowing for complex rule stacking between behaviors. [Cache Rules](https://developers.cloudflare.com/cache/how-to/cache-rules/) became a dedicated, expressive rule type for caching decisions, joined by [CDN-Cache-Control](https://developers.cloudflare.com/cache/concepts/cdn-cache-control/), [Origin Cache Control](https://developers.cloudflare.com/cache/concepts/cache-control/), [custom cache keys](https://developers.cloudflare.com/cache/how-to/cache-rules/examples/custom-cache-key/), and other controls that give you precise ways to tell Cloudflare what's safe to cache, for how long, and under what conditions. Many of these controls share a common trait: they operate on the *request*. While maybe unintuitive, this makes sense. The most important caching decisions Cloudflare has to make are *should we look this up in cache, and under what key?* This question has to be answered *before* Cloudflare talks to the origin. If the answer is "no" when it should have been "yes," the request has already paid for the origin round trip and there's nothing the response can do to give it back that latency. Request-time rules answer that question using the only information available at that moment: the URL, the requested file’s extension, the request headers, geography, device type, and so on. Using these request parameters and the rules set to change these request parameters, we determine if something is likely in cache and look there before talking with the origin. But some cache decisions cannot be made on the request. The origin's `Cache-Control` directives (cache-control: max-age=3600) are part of the response Cloudflare receives from the origin. The status code, the ETag, the Last-Modified timestamp, Set-Cookie, and the cache-tag format the origin chooses are all things in the response that the origin passes to the cache. None of it is available when request-time rules run. Responses from the origin are the source of truth, so if something needed to be changed on Cloudflare that wasn’t available at request time, that previously left you with three workarounds: Each of those costs engineering time, adds latency, or burns money. **Cache Response Rules give you a fourth option: a ruleset where you can modify the origin's response before it hits Cloudflare's cache.** The cleanest way to think about the difference between [**Cache Rules**](https://developers.cloudflare.com/cache/how-to/cache-rules/) and the new [**Cache Response Rules**](https://developers.cloudflare.com/cache/how-to/cache-response-rules/) is as two phases, each answering its own question. `cache-control` directives that tell Cloudflare whether and how to cache The response phase can't do everything the request phase can. It can't change the **what,** as the key is already fixed. Though it can change **whether** and **how** Cloudflare caches, for example, a response rule can set `no-store` to make a cacheable object non-cacheable or strip a `Set-Cookie` to make non-cacheable content eligible for cache. However, Cache Response Rules can't make a previously ineligible request cacheable by the response phase, because it’s too late. So Cache Response Rules don't replace Cache Rules. Cache Rules decide **whether**, **what**, and **how** we cache on the request. Cache Response Rules get the final word on the **how** and **whether**, once the origin's response is seen by Cloudflare in a phase that didn't exist before. Cache Response Rules support three actions today. The `set_cache_settings` action removes things like `Set-Cookie, ETag`, or `Last-Modified` from the origin response before Cloudflare evaluates it for caching: This is the fix for the `Set-Cookie-on-a-static-asset` problem. Origin frameworks frequently attach session cookies to every response (for load balancing or other purposes), including responses for assets that users don't want to be associated with a session. Stripping `Set-Cookie` in the response phase makes those assets cacheable again without asking the origin, load balancer, or anything else upstream to change anything. Cache Response Rules also run on responses that aren't eligible for caching at all. So when you strip Set-Cookie from a dynamic response, for instance, the rule fires whether or not the object is ever stored. This allows you to control what the client sees even when the response is not stored in cache. You can also strip ETag and `Last-Modified`, which is useful when those headers are misconfigured at the origin and causing thrash. This comes with a tradeoff: stripping both ETag and Last-Modified enables [Smart Edge Revalidation](https://blog.cloudflare.com/introducing-smart-edge-revalidation/) for that response. If Cache Response Rules then *add* new validators, Cloudflare will not enable a Smart Edge Revalidation for browser conditional requests. So stripping and modifying headers, even on dynamic requests, are a powerful new pattern that did not exist before on Cloudflare, but there can be additional configs to be aware of if you make these changes. `set_cache_tags` lets you `add`, `remove`, or `set` cache tags used for [purge by tag](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/) on the response. Tags can be static: Or computed from a response header expression: That second form is the one that earns its keep during a CDN migration. If your previous CDN attached surrogate keys to responses using a header like `Surrogate-Keys` with a comma delimiter, you can translate them into Cloudflare's `Cache-Tag` format directly in the response phase. The third argument to split() is the limit: the maximum number of elements in the resulting array can be between 1 and 128. Use a value comfortably larger than the realistic tag count per response. The value 1 would return the entire header as a single tag. Once tags exist on the response, [purge-by-tag](https://blog.cloudflare.com/instant-purge/) just works (and by “works” we mean usually in [under 150 ms, globally](https://blog.cloudflare.com/instant-purge/)). `set_cache_control` is the action that does the most heavy lifting. You can set or remove individual directives: `max-age`, `s-maxage`, `stale-if-error`, `stale-while-revalidate``private`, `no-cache` (with optional header-name qualifiers)`no-store`, `no-transform`, `must-revalidate`, `proxy-revalidate`, `must-understand`, `public`, `immutable` For each directive you can also set `cloudflare_only`: true, which is the part that often surprises people: When `cloudflare_only` is true, the directive affects how Cloudflare caches the response, but the downstream Cache-Control value sent to the browser is left alone. This is the response-phase version of what `CDN-Cache-Control` gives you at the origin: cache the asset for 24 hours at Cloudflare, but tell the browser something else. The difference is that you're now doing it from a Rules surface in the Cloudflare dashboard, rather than asking the origin to set a separate header. Below are some examples we thought could help show you the power of Cache Response Rules. Try them out, remix them, and share with others in the community so you can see how to achieve powerful cache customizations using Cache Rules with Cache Response Rules. More examples can be found in the [docs](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/#example-requests). *Why it works*: The most common cause of "this should be cacheable but isn't" is a session middleware on the origin that attaches a `Set-Cookie` to *every* response. Stripping it for known-static extensions converts those responses to cacheable without any origin change. *Caveat*: Only do this for asset types where the cookie is not semantically required. If your origin uses cookies to drive variant behavior on those URLs (very unusual but possible), strip selectively or scope stripping these headers by path. *Why it works*: Cloudflare holds the asset for a month and serves it from cache. Browsers see `max-age=86400` and re-validate after a day. You decouple the two cache lifetimes without touching the origin. *Caveat*: `immutable` tells browsers not to revalidate even on explicit refresh. Pair it only with versioned/hashed filenames. *Why it works*: Framework defaults sometimes attach `no-cache` to every response. If you know /static/\* is safe to cache, you can strip the directive and impose your own TTL (at Cloudflare only), without changing what the origin or any downstream cache sees. *Caveat*: Be honest about what's actually static. If `/static/` is sometimes used to serve user-specific content, narrow the match (extension, response header signal, content type). *Why it works*: A lot of CDN migration pain comes from origin tooling that emits cache-tag headers in another vendor's format. Instead of asking the origin team to ship a release that adds Cloudflare's `Cache-Tag`, translate the existing header in the response phase. Purge-by-tag on Cloudflare starts working immediately. *Caveat*: The third argument to split() is the limit (1–128) on the resulting array size, not anything to do with the separator. **Dashboard** Rules in this phase live at: For further information about how to use Cache Response Rules including API and terraform examples, please see the [documentation](https://developers.cloudflare.com/cache/how-to/cache-response-rules/create-api/). Cache Rules saw the request. Cache Response Rules see the response. Both give you even more control to build the perfect cache on Cloudflare. They are available on all plans today — go [try them](http://dash.cloudflare.com/?to=/:account/:zone/caching/rules/response-rules/new) out!