
<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>Mon, 13 Apr 2026 16:55:06 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[15 years of helping build a better Internet: a look back at Birthday Week 2025]]></title>
            <link>https://blog.cloudflare.com/birthday-week-2025-wrap-up/</link>
            <pubDate>Mon, 29 Sep 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Rust-powered core systems, post-quantum upgrades, developer access for students, PlanetScale integration, open-source partnerships, and our biggest internship program ever — 1,111 interns in 2026. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare launched fifteen years ago with a mission to help build a better Internet. Over that time the Internet has changed and so has what it needs from teams like ours.  In this year’s <a href="https://blog.cloudflare.com/cloudflare-2025-annual-founders-letter/"><u>Founder’s Letter</u></a>, Matthew and Michelle discussed the role we have played in the evolution of the Internet, from helping encryption grow from 10% to 95% of Internet traffic to more recent challenges like how people consume content. </p><p>We spend Birthday Week every year releasing the products and capabilities we believe the Internet needs at this moment and around the corner. Previous <a href="https://blog.cloudflare.com/tag/birthday-week/"><u>Birthday Weeks</u></a> saw the launch of <a href="https://blog.cloudflare.com/introducing-cloudflares-automatic-ipv6-gatewa/"><u>IPv6 gateway</u></a> in 2011,  <a href="https://blog.cloudflare.com/introducing-universal-ssl/"><u>Universal SSL</u></a> in 2014, <a href="https://blog.cloudflare.com/introducing-cloudflare-workers/"><u>Cloudflare Workers</u></a> and <a href="https://blog.cloudflare.com/unmetered-mitigation/"><u>unmetered DDoS protection</u></a> in 2017, <a href="https://blog.cloudflare.com/introducing-cloudflare-radar/"><u>Cloudflare Radar</u></a> in 2020, <a href="https://www.cloudflare.com/developer-platform/products/r2/"><u>R2 Object Storage</u></a> with zero egress fees in 2021,  <a href="https://blog.cloudflare.com/post-quantum-tunnel/"><u>post-quantum upgrades for Cloudflare Tunnel</u></a> in 2022, <a href="https://blog.cloudflare.com/best-place-region-earth-inference/"><u>Workers AI</u></a> and <a href="https://blog.cloudflare.com/announcing-encrypted-client-hello/"><u>Encrypted Client Hello</u></a> in 2023. And those are just a sample of the launches.</p><p>This year’s themes focused on helping prepare the Internet for a new model of monetization that encourages great content to be published, fostering more opportunities to build community both inside and outside of Cloudflare, and evergreen missions like making more features available to everyone and constantly improving the speed and security of what we offer.</p><p>We shipped a lot of new things this year. In case you missed the dozens of blog posts, here is a breakdown of everything we announced during Birthday Week 2025. </p><p><b>Monday, September 22</b></p>
<div><table><thead>
  <tr>
    <th><span>What</span></th>
    <th><span>In a sentence …</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://blog.cloudflare.com/cloudflare-1111-intern-program/?_gl=1*rxpw9t*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MTgwNzEkajI4JGwwJGgw"><span>Help build the future: announcing Cloudflare’s goal to hire 1,111 interns in 2026</span></a></td>
    <td><span>To invest in the next generation of builders, we announced our most ambitious intern program yet with a goal to hire 1,111 interns in 2026.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/supporting-the-future-of-the-open-web/?_gl=1*1l701kl*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MTg0MDMkajYwJGwwJGgw"><span>Supporting the future of the open web: Cloudflare is sponsoring Ladybird and Omarchy</span></a></td>
    <td><span>To support a diverse and open Internet, we are now sponsoring Ladybird (an independent browser) and Omarchy (an open-source Linux distribution and developer environment).</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/new-hubs-for-startups/?_gl=1*s35rml*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MTg2NjEkajYwJGwwJGgw/"><span>Come build with us: Cloudflare’s new hubs for startups</span></a></td>
    <td><span>We are opening our office doors in four major cities (San Francisco, Austin, London, and Lisbon) as free hubs for startups to collaborate and connect with the builder community.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/ai-crawl-control-for-project-galileo/?_gl=1*n9jmji*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MTg2ODUkajM2JGwwJGgw"><span>Free access to Cloudflare developer services for non-profit and civil society organizations</span></a></td>
    <td><span>We extended our Cloudflare for Startups program to non-profits and public-interest organizations, offering free credits for our developer tools.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/workers-for-students/?_gl=1*lq39wt*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MTg3NDgkajYwJGwwJGgw"><span>Introducing free access to Cloudflare developer features for students</span></a></td>
    <td><span>We are removing cost as a barrier for the next generation by giving students with .edu emails 12 months of free access to our paid developer platform features.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/capnweb-javascript-rpc-library/?_gl=1*19mcm4k*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjA2MTgkajYwJGwwJGgw"><span>Cap’n Web: a new RPC system for browsers and web servers</span></a></td>
    <td><span>We open-sourced Cap'n Web, a new JavaScript-native RPC protocol that simplifies powerful, schema-free communication for web applications.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/workers-launchpad-006/?_gl=1*8z9nf6*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjA3MTckajUwJGwwJGgw"><span>A lookback at Workers Launchpad and a warm welcome to Cohort #6</span></a></td>
    <td><span>We announced Cohort #6 of the Workers Launchpad, our accelerator program for startups building on Cloudflare.</span></td>
  </tr>
</tbody></table></div><p><b>Tuesday, September 23</b></p>
<div><table><thead>
  <tr>
    <th><span>What</span></th>
    <th><span>In a sentence …</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://blog.cloudflare.com/per-customer-bot-defenses/?_gl=1*1i1oipn*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjA3NjAkajckbDAkaDA./"><span>Building unique, per-customer defenses against advanced bot threats in the AI era</span></a></td>
    <td><span>New anomaly detection system that uses machine learning trained on each zone to build defenses against AI-driven bot attacks. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/cloudflare-astro-tanstack/?_gl=1*v1uhzx*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjE2MzckajYwJGwwJGgw"><span>Why Cloudflare, Netlify, and Webflow are collaborating to support Open Source tools</span></a></td>
    <td><span>To support the open web, we joined forces with Webflow to sponsor Astro, and with Netlify to sponsor TanStack.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/x402/?_gl=1*kizcyy*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjA5OTUkajYkbDAkaDA./"><span>Launching the x402 Foundation with Coinbase, and support for x402 transactions</span></a></td>
    <td><span>We are partnering with Coinbase to create the x402 Foundation, encouraging the adoption of the </span><a href="https://github.com/coinbase/x402?cf_target_id=4D4A124640BFF471F5B56706F9A86B34"><span>x402 protocol</span></a><span> to allow clients and services to exchange value on the web using a common language</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/ai-crawl-control-for-project-galileo/?_gl=1*1r1zsjt*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjE3NjYkajYwJGwwJGgw"><span>Helping protect journalists and local news from AI crawlers with Project Galileo</span></a></td>
    <td><span>We are extending our free Bot Management and AI Crawl Control services to journalists and news organizations through Project Galileo.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/confidence-score-rubric/"><span>Cloudflare Confidence Scorecards - making AI safer for the Internet</span></a></td>
    <td><span>Automated evaluation of AI and SaaS tools, helping organizations to embrace AI without compromising security.</span></td>
  </tr>
</tbody></table></div><p><b>Wednesday, September 24</b></p>
<div><table><thead>
  <tr>
    <th><span>What</span></th>
    <th><span>In a sentence …</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://blog.cloudflare.com/automatically-secure/?_gl=1*8mjfiy*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjE4MTckajkkbDAkaDA."><span>Automatically Secure: how we upgraded 6,000,000 domains by default</span></a></td>
    <td><span>Our Automatic SSL/TLS system has upgraded over 6 million domains to more secure encryption modes by default and will soon automatically enable post-quantum connections.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/content-signals-policy/?_gl=1*lfy031*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjE5NTkkajYwJGwwJGgw/"><span>Giving users choice with Cloudflare’s new Content Signals Policy</span></a></td>
    <td><span>The Content Signals Policy is a new standard for robots.txt that lets creators express clear preferences for how AI can use their content.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/building-a-better-internet-with-responsible-ai-bot-principles/?_gl=1*hjo4nx*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjIwMTIkajckbDAkaDA."><span>To build a better Internet in the age of AI, we need responsible AI bot principles</span></a></td>
    <td><span>A proposed set of responsible AI bot principles to start a conversation around transparency and respect for content creators' preferences.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/saas-to-saas-security/?_gl=1*tigi23*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjIwNjgkajYwJGwwJGgw"><span>Securing data in SaaS to SaaS applications</span></a></td>
    <td><span>New security tools to give companies visibility and control over data flowing between SaaS applications.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/post-quantum-warp/?_gl=1*1vy23vv*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjIyMDIkajYwJGwwJGgw"><span>Securing today for the quantum future: WARP client now supports post-quantum cryptography (PQC)</span></a></td>
    <td><span>Cloudflare’s WARP client now supports post-quantum cryptography, providing quantum-resistant encryption for traffic. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/a-simpler-path-to-a-safer-internet-an-update-to-our-csam-scanning-tool/?_gl=1*1avvoeq*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjIxMTUkajEzJGwwJGgw"><span>A simpler path to a safer Internet: an update to our CSAM scanning tool</span></a></td>
    <td><span>We made our CSAM Scanning Tool easier to adopt by removing the need to create and provide unique credentials, helping more site owners protect their platforms.</span></td>
  </tr>
</tbody></table></div><p>
<b>Thursday, September 25</b></p>
<div><table><thead>
  <tr>
    <th><span>What</span></th>
    <th><span>In a sentence …</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://blog.cloudflare.com/enterprise-grade-features-for-all/?_gl=1*ll2laa*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjIyODIkajYwJGwwJGgw/"><span>Every Cloudflare feature, available to everyone</span></a></td>
    <td><span>We are making every Cloudflare feature, starting with Single Sign On (SSO), available for anyone to purchase on any plan. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/cloudflare-developer-platform-keeps-getting-better-faster-and-more-powerful/?_gl=1*1dwrmxx*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI0MzgkajYwJGwwJGgw/"><span>Cloudflare's developer platform keeps getting better, faster, and more powerful</span></a></td>
    <td><span>Updates across Workers and beyond for a more powerful developer platform – such as support for larger and more concurrent Container images, support for external models from OpenAI and Anthropic in AI Search (previously AutoRAG), and more. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/planetscale-postgres-workers/?_gl=1*1e87q21*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI2MDUkajYwJGwwJGgw"><span>Partnering to make full-stack fast: deploy PlanetScale databases directly from Workers</span></a></td>
    <td><span>You can now connect Cloudflare Workers to PlanetScale databases directly, with connections automatically optimized by Hyperdrive.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/cloudflare-data-platform/?_gl=1*1gj7lyv*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI5MDckajYwJGwwJGgw"><span>Announcing the Cloudflare Data Platform</span></a></td>
    <td><span>A complete solution for ingesting, storing, and querying analytical data tables using open standards like Apache Iceberg. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/r2-sql-deep-dive/?_gl=1*88kngf*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI5MzAkajM3JGwwJGgw"><span>R2 SQL: a deep dive into our new distributed query engine</span></a></td>
    <td><span>A technical deep dive on R2 SQL, a serverless query engine for petabyte-scale datasets in R2.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/safe-in-the-sandbox-security-hardening-for-cloudflare-workers/?_gl=1*y25my1*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI4ODQkajMkbDAkaDA./"><span>Safe in the sandbox: security hardening for Cloudflare Workers</span></a></td>
    <td><span>A deep-dive into how we’ve hardened the Workers runtime with new defense-in-depth security measures, including V8 sandboxes and hardware-assisted memory protection keys.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/sovereign-ai-and-choice/?_gl=1*1gvqucw*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI4NjkkajE4JGwwJGgw/"><span>Choice: the path to AI sovereignty</span></a></td>
    <td><span>To champion AI sovereignty, we've added locally-developed open-source models from India, Japan, and Southeast Asia to our Workers AI platform.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/email-service/?_gl=1*z3yus0*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI4MjckajYwJGwwJGgw"><span>Announcing Cloudflare Email Service’s private beta</span></a></td>
    <td><span>We announced the Cloudflare Email Service private beta, allowing developers to reliably send and receive transactional emails directly from Cloudflare Workers.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/nodejs-workers-2025/?_gl=1*gzumry*_gcl_aw*R0NMLjE3NTg5MTQ0ODEuQ2p3S0NBanc4OWpHQmhCMEVpd0EybzFPbnp1VkVIN2UybUZJcERvWWtJMV9Rc2FlbTFEV19FU19qVjR1QnVmcEE3QVdkeU9zaVRIZGl4b0N4dHNRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3NTgyMDc1NDEuQ2owS0NRancyNjdHQmhDU0FSSXNBT2pWSjRIWTFOVTZVWDFyVEJVNGNyd243d3RwX3lheFBuNnZJdXJlOUVmWmRzWkJJa1ZyejF4cDFDSWFBa2pBRUFMd193Y0I.*_gcl_au*MTI5NDk3ODE3OC4xNzUzMTQwMzIw*_ga*ZTI0NWUyMDQtZDM1YS00NTFkLWIwM2UtYjhhNzliZWQxY2Nj*_ga_SQCRB0TXZW*czE3NTg5MTY5NDEkbzYkZzEkdDE3NTg5MjI2ODgkajYwJGwwJGgw/"><span>A year of improving Node.js compatibility in Cloudflare Workers</span></a></td>
    <td><span>There are hundreds of new Node.js APIs now available that make it easier to run existing Node.js code on our platform. </span></td>
  </tr>
</tbody></table></div><p><b>Friday, September 26</b></p>
<table><thead>
  <tr>
    <th><span>What</span></th>
    <th><span>In a sentence …</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><a href="https://blog.cloudflare.com/20-percent-internet-upgrade"><span>Cloudflare just got faster and more secure, powered by Rust</span></a></td>
    <td><span>We have re-engineered our core proxy with a new modular, Rust-based architecture, cutting median response time by 10ms for millions. </span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com//introducing-observatory-and-smart-shield/"><span>Introducing Observatory and Smart Shield</span></a></td>
    <td><span>New monitoring tools in the Cloudflare dashboard that provide actionable recommendations and one-click fixes for performance issues.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/monitoring-as-sets-and-why-they-matter/"><span>Monitoring AS-SETs and why they matter</span></a></td>
    <td><span>Cloudflare Radar now includes Internet Routing Registry (IRR) data, allowing network operators to monitor AS-SETs to help prevent route leaks.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/an-ai-index-for-all-our-customers"><span>An AI Index for all our customers</span></a></td>
    <td><span>We announced the private beta of AI Index, a new service that creates an AI-optimized search index for your domain that you control and can monetize.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/new-regional-internet-traffic-and-certificate-transparency-insights-on-radar/"><span>Introducing new regional Internet traffic and Certificate Transparency insights on Cloudflare Radar</span></a></td>
    <td><span>Sub-national traffic insights and Certificate Transparency dashboards for TLS monitoring.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/eliminating-cold-starts-2-shard-and-conquer/"><span>Eliminating Cold Starts 2: shard and conquer</span></a></td>
    <td><span>We have reduced Workers cold starts by 10x by implementing a new "worker sharding" system that routes requests to already-loaded Workers.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/network-performance-update-birthday-week-2025/"><span>Network performance update: Birthday Week 2025</span></a></td>
    <td><span>The TCP Connection Time (Trimean) graph shows that we are the fastest TCP connection time in 40% of measured ISPs – and the fastest across the top networks.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/how-cloudflare-uses-the-worlds-greatest-collection-of-performance-data/"><span>How Cloudflare uses performance data to make the world’s fastest global network even faster</span></a></td>
    <td><span>We are using our network's vast performance data to tune congestion control algorithms, improving speeds by an average of 10% for QUIC traffic.</span></td>
  </tr>
  <tr>
    <td><a href="https://blog.cloudflare.com/code-mode/"><span>Code Mode: the better way to use MCP</span></a></td>
    <td><span>It turns out we've all been using MCP wrong. Most agents today use MCP by exposing the "tools" directly to the LLM. We tried something different: Convert the MCP tools into a TypeScript API, and then ask an LLM to write code that calls that API. The results are striking.</span></td>
  </tr>
</tbody></table>
    <div>
      <h3>Come build with us!</h3>
      <a href="#come-build-with-us">
        
      </a>
    </div>
    <p>Helping build a better Internet has always been about more than just technology. Like the announcements about interns or working together in our offices, the community of people behind helping build a better Internet matters to its future. This week, we rolled out our most ambitious set of initiatives ever to support the builders, founders, and students who are creating the future.</p><p>For founders and startups, we are thrilled to welcome <b>Cohort #6</b> to the <b>Workers Launchpad</b>, our accelerator program that gives early-stage companies the resources they need to scale. But we’re not stopping there. We’re opening our doors, literally, by launching <b>new physical hubs for startups</b> in our San Francisco, Austin, London, and Lisbon offices. These spaces will provide access to mentorship, resources, and a community of fellow builders.</p><p>We’re also investing in the next generation of talent. We announced <b>free access to the Cloudflare developer platform for all students</b>, giving them the tools to learn and experiment without limits. To provide a path from the classroom to the industry, we also announced our goal to hire <b>1,111 interns in 2026</b> — our biggest commitment yet to fostering future tech leaders.</p><p>And because a better Internet is for everyone, we’re extending our support to <b>non-profits and public-interest organizations</b>, offering them free access to our production-grade developer tools, so they can focus on their missions.</p><p>Whether you're a founder with a big idea, a student just getting started, or a team working for a cause you believe in, we want to help you succeed.</p>
    <div>
      <h3>Until next year</h3>
      <a href="#until-next-year">
        
      </a>
    </div>
    <p>Thank you to our customers, our community, and the millions of developers who trust us to help them build, secure, and accelerate the Internet. Your curiosity and feedback drive our innovation.</p><p>It’s been an incredible 15 years. And as always, we’re just getting started!</p><p><i>(Watch the full conversation on our show </i><a href="ThisWeekinNET.com"><i>ThisWeekinNET.com</i></a><i> about what we launched during Birthday Week 2025 </i><a href="https://youtu.be/Z2uHFc9ua9s?feature=shared"><i><b><u>here</u></b></i></a><i>.) </i></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Workers Launchpad]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[1.1.1.1]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Application Services]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[CDN]]></category>
            <category><![CDATA[Cloudflare for Startups]]></category>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[Cloudflare Zero Trust]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <guid isPermaLink="false">4k1NhJtljIsH7GOkpHg1Ei</guid>
            <dc:creator>Nikita Cano</dc:creator>
            <dc:creator>Korinne Alpers</dc:creator>
        </item>
        <item>
            <title><![CDATA[Quicksilver v2: evolution of a globally distributed key-value store (Part 2)]]></title>
            <link>https://blog.cloudflare.com/quicksilver-v2-evolution-of-a-globally-distributed-key-value-store-part-2-of-2/</link>
            <pubDate>Thu, 17 Jul 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ This is part two of a story about how we overcame the challenges of making a complex system more scalable. ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>What is Quicksilver?</h2>
      <a href="#what-is-quicksilver">
        
      </a>
    </div>
    <p>Cloudflare has servers in <a href="https://www.cloudflare.com/network"><u>330 cities spread across 125+ countries</u></a>. All of these servers run Quicksilver, which is a key-value database that contains important configuration information for many of our services, and is queried for all requests that hit the Cloudflare network.</p><p>Because it is used while handling requests, Quicksilver is designed to be very fast; it currently responds to 90% of requests in less than 1 ms and 99.9% of requests in less than 7 ms. Most requests are only for a few keys, but some are for hundreds or even more keys.</p><p>Quicksilver currently contains over five billion key-value pairs with a combined size of 1.6 TB, and it serves over three billion keys per second, worldwide. Keeping Quicksilver fast provides some unique challenges, given that our dataset is always growing, and new use cases are added regularly.</p><p>Quicksilver used to store all key-values on all servers everywhere, but there is obviously a limit to how much disk space can be used on every single server. For instance, the more disk space used by Quicksilver, the less disk space is left for content caching. Also, with each added server that contains a particular key-value, the cost of storing that key-value increases.</p><p>This is why disk space usage has been the main battle that the Quicksilver team has been waging over the past several years. A lot was done over the years, but we now think that we have finally created an architecture that will allow us to get ahead of the disk space limitations and finally make Quicksilver scale better.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2mGYCFdZIWdYl1TuDzvlAf/45d1b975adce0ec4eb5cc2842c8bd185/image1.png" />
          </figure><p><sup>The size of the Quicksilver database has grown by 50% to about 1.6 TB in the past year</sup></p>
    <div>
      <h2>What we talked about previously</h2>
      <a href="#what-we-talked-about-previously">
        
      </a>
    </div>
    <p><a href="https://blog.cloudflare.com/quicksilver-v2-evolution-of-a-globally-distributed-key-value-store-part-1/"><u>Part one of the story</u></a> explained how Quicksilver V1 stored all key-value pairs on each server all around the world. It was a very simple and fast design, it worked very well, and it was a great way to get started. But over time, it turned out to not scale well from a disk space perspective.</p><p>The problem was that disk space was running out so fast that there was not enough time to design and implement a fully scalable version of Quicksilver. Therefore, Quicksilver V1.5 was created first. It halved the disk space used on each server compared to V1.</p><p>For this, a new <i>proxy </i>mode was introduced for Quicksilver. In this mode, Quicksilver does not contain the full dataset anymore, but only contains a cache. All cache misses are looked up on another server that runs Quicksilver with a full dataset. Each server runs about ten separate <i>instances</i> of Quicksilver, and all have different databases with different sets of key-values. We call Quicksilver instances with the full data set <i>replicas</i>.</p><p>For Quicksilver V1.5, half of those instances on a particular server would run Quicksilver in proxy mode, and therefore would not have the full dataset anymore. The other half would run in replica mode. This worked well for a time, but it was not the final solution.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2GHG0tl5diZ7w09qNkblyd/6fa0ba250477cb9027496669640a0acb/image4.png" />
          </figure><p>Building this intermediate solution had the added benefit of allowing the team to gain experience running an even more distributed version of Quicksilver.</p>
    <div>
      <h2>The problem</h2>
      <a href="#the-problem">
        
      </a>
    </div>
    <p>There were a few reasons why Quicksilver V1.5 was not fully scalable.</p><p>First, the size of the separate instances were not very stable. The key-space is owned by the teams that use Quicksilver, not by the Quicksilver team, and the way those teams use Quicksilver changes frequently. Furthermore, while most instances grow in size over time, some instances have actually gotten smaller, such as when the use of Quicksilver is optimised by teams. The result of this is that the split of instances that was well-balanced at the start, quickly became unbalanced.</p><p>Second, the analyses that were done to estimate how much of the key space would need to be in cache on each server assumed that taking all keys that were accessed in a three-day period would represent a good enough cache. This assumption turned out to be wildly off. This analysis estimated that we needed about 20% of the key space in cache, which turned out to not be entirely accurate. Whereas most instances did have a good cache hit rate, with 20% or less of the key space in cache, some instances turned out to need a much higher percentage.</p><p>The main issue, however, was that reducing the disk space used by Quicksilver on our network by as much as 40% does not actually make it more scalable. The number of key-values that are stored in Quicksilver keeps growing. It only took about two years before disk space was running low again.</p>
    <div>
      <h2>The solution</h2>
      <a href="#the-solution">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4G3Y1t9OeF7BlsASIwlpI7/8df9e21affde869fbdd41f203cbcd256/image6.png" />
          </figure><p><sup>Except for a handful of special storage servers, Quicksilver does not contain the full dataset anymore, but only cache. Any cache misses will be looked up in replicas on our storage servers, which do have the full dataset.</sup></p><p>The solution to the scalability problem was brought on by a new insight. As it turns out, numerous key-values were actually almost never used. We call these <i>cold keys</i>. There are different reasons for these cold keys: some of them were old and not well cleaned up, some were used only in certain regions or in certain data centers, and some were not used for a very long time or maybe not at all (a domain name that is never looked up for example or a script that was uploaded but never used).</p><p>At first, the team had been considering solving our scalability problem by splitting up the entire dataset into shards and distributing those across the servers in the different data centers. But sharding the full dataset adds a lot of complexity, corner cases, and unknowns. Sharding also does not optimize for data locality. For example, if the key-space is split into 4 shards and each server gets one shard, that server can only serve 25% of the requested keys from its local database. The cold keys would also still be contained in those shards and would take up disk space unnecessarily.</p><p>Another data structure that is much better at data locality and explicitly avoids storing keys that are never used is a cache. So it was decided that only a handful of servers with large disks would maintain the full data set, and all other servers would only have a cache. This was an obvious evolution from Quicksilver V1.5. Caching was already being done on a smaller scale, so all the components were already available. The caching proxies and the inter-data center discovery mechanisms were already in place. They had been used since 2021 and were therefore thoroughly battle tested. However, one more component needed to be added.</p><p>There was a concern that having all instances on all servers connect to a handful of storage nodes with replicas would overload them with too many connections. So a Quicksilver <i>relay</i> was added. For each instance, a few servers would be elected within each data center on which Quicksilver would run in relay mode. The relays would maintain the connections to the replicas on the storage nodes. All proxies inside a data center would discover those relays and all cache misses would be relayed through them to the replicas.</p><p>This new architecture worked very well. The cache hit rates still needed some improvement, however.</p>
    <div>
      <h3>Prefetching the future</h3>
      <a href="#prefetching-the-future">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/48FbryG5MCUAmQNY34jtOK/5e57c62fafa81fa323cf4ef77ccded55/Prefetching_the_future.png" />
          </figure><p><sup>Every resolved cache miss is prefetched by all servers in the data center</sup></p><p>We had a hypothesis that prefetching all keys that were cache misses on the other servers inside the same data center would improve the cache hit rate. So an analysis was done, and it indeed showed that every key that was a cache miss on one server in a data center had a very high probability of also being a cache miss on another server in the same data center sometime in the near future. Therefore, a mechanism was built that distributed all resolved cache misses on relays to all other servers.</p><p>All cache misses in a data center are resolved by requesting them from a relay, which subsequently forwards the requests to one of the replicas on the storage nodes. Therefore, the prefetching mechanism was implemented by making relays publish a stream of all resolved cache misses, to which all Quicksilver proxies in the same data center subscribe. The resulting key-values were then added to the proxy local caches.</p><p>This strategy is called <i>reactive</i> prefetching, because it fills caches only with the key-values that directly resulted from cache misses inside the same data center. Those prefetches are a <i>reaction</i> to the cache misses. Another way of prefetching is called <i>predictive</i> prefetching, in which an algorithm tries to predict which keys that have not yet been requested will be requested in the near future. A few approaches for making these predictions were tried, but they did not result in any improvement, and so this idea was abandoned.</p><p>With the prefetching enabled, cache hit rates went up to about 99.9% for the worst performing instance. This was the goal that we were trying to reach. But while rolling this out to more of our network, it turned out that there was one team that needed an even higher cache hit rate, because the tail latencies they were seeing with this new architecture were too high.</p><p>This team was using a Quicksilver instance called <i>dnsv2</i>. This is a very latency sensitive instance, because it is the one from which DNS queries are served. Some of the DNS queries under the hood need multiple queries to Quicksilver, so any added latency to Quicksilver multiplies for them. This is why it was decided that one more improvement to the Quicksilver cache was needed.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7fKjcIASCIsaW52NDTF6OX/25cc40046536b28fca5b44249234cc48/image12.png" />
          </figure><p><sup>The level 1 cache hit-rate is 99.9% or higher, on average.</sup></p>
    <div>
      <h3>Back to the sharding</h3>
      <a href="#back-to-the-sharding">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/10ur3qVEVDt4carNCqldch/0777d16f53fd501354f7196caac4d9fe/back-to-sharding.png" />
          </figure><p><sup>Before going to a replica in another data center, a cache miss is first looked up in a data center-wide sharded cache</sup></p><p>The instance on which higher cache hit rates were required was also the instance on which the cache performed the worst. The cache works with a retention time, defined as the number of days a key-value is kept in cache after it was last accessed, after which it is evicted from the cache. An analysis of the cache showed that this instance needed a much longer retention time. But, a higher retention time also causes the cache to take up more disk space — space that was not available.</p><p>However, while running Quicksilver V1.5, we had already noticed the pattern that caches generally performed much better in smaller data centers as compared to larger ones. This sparked the hypothesis that led to the final improvement.</p><p>It turns out that smaller data centers, with fewer servers, generally needed less disk space for their cache. Vice versa, the more servers there are in a data center, the larger the Quicksilver cache needs to be. This is easily explained by the fact that larger data centers generally serve larger populations, and therefore have a larger diversity of requests. More servers also means more total disk space available inside the data center. To be able to make use of this pattern the concept of sharding was reintroduced.</p><p>Our key space was split up into multiple shards. Each server in a data center was assigned one of the shards. Instead of those shards containing the full dataset for their part of the key space, they contain a cache for it. Those cache shards are populated by all cache misses inside the data center. This all forms a data center-wide cache that is distributed using sharding.</p><p>The data locality issue that sharding the full dataset has, as described above, is solved by keeping the local per-server caches as well. The sharded cache is in addition to the local caches. All servers in a data center contain both their local cache and a cache for one physical shard of the sharded cache. Therefore, each requested key is first looked up in the server’s local cache, after that the data center-wide sharded cache is queried, and finally if both caches miss the requested key, it is looked up on one of the storage nodes.</p><p>The key space is split up into separate shards by first dividing hashes of the keys by range into 1024 logical shards. Those logical shards are then divided up into physical shards, again by range. Each server gets one physical shard assigned by repeating the same process on the server hostname.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4fKK9EPdwP69l4VtIErNGW/5481fb93b8e89fff6f5bdc6dd2dfbb44/image7.png" />
          </figure><p><sup>Each server contains one physical shard. A physical shard contains a range of logical shards. A local shard contains a range of the ordered set that result from hashing all keys.</sup></p><p>This approach has the advantage that the sharding factor can be scaled up by factors of two without the need for copying caches to other servers. When the sharding factor is increased in this way, the servers will automatically get a new physical shard assigned that contains a subset of the key space that the previous physical shard on that server contained. After this has happened, their cache will contain supersets of the needed cache. The key-values that are not needed anymore will be evicted over time.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2IBc0EMQEDeenGX2ShbrrM/d661ef58d7114caa3c77b9eb5b18b736/image10.png" />
          </figure><p><sup>When the number of physical shards are doubled the servers will automatically get new physical shards that are subsets of their previous physical shards, therefore still have the relevant key-values in cache.</sup></p><p>This approach means that the sharded caches can easily be scaled up when needed as the number of keys that are in Quicksilver grows, and without any need for relocating data. Also, shards are well-balanced due to the fact that they contain uniform random subsets of a very large key-space.</p><p>Adding new key-values to the physical cache shards piggybacks on the prefetching mechanism, which already distributes all resolved cache misses to all servers in a data center. The keys that are part of the key space for a physical shard on a particular server are just kept longer in cache than the keys that are not part of that physical shard.</p><p>Another reason why a sharded cache is simpler than sharding the full key-space is that it is possible to cut some corners with a cache. For instance, looking up older versions of key-values (as used for  multiversion concurrency control) is not supported on cache shards. As explained in an <a href="https://blog.cloudflare.com/quicksilver-v2-evolution-of-a-globally-distributed-key-value-store-part-1/"><u>earlier blog post</u></a>, this is needed for consistency when looking up key-values on different servers, when that server has a newer version of the database. It is not needed in the cache shards, because lookups can always fall back to the storage nodes when the right version is not available.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7qKie4ZFES4yJw1Sa2K26X/3d326d4e8e7553dcf96738ceae7229fe/image9.png" />
          </figure><p><sup>Proxies have a recent keys window that contains all recently written key-values. A cache shard only has its cached key-values. Storage replicas contain all key-values and on top of that they contain multiple versions for recently written key-values. When the proxy, that has database version 1000, has a cache miss for </sup><sup><i>key1</i></sup><sup> it can be seen that the version of that key on the cache shard was written at database version 1002 and therefore is too new. This means that it is not consistent with the proxy’s database version. This is why the relay will fetch that key from a replica instead, which can return the earlier consistent version. In contrast, </sup><sup><i>key2</i></sup><sup> on the cache shard can be used, because it was written at index 994, well below the database version of the proxy.</sup></p><p>There is only one very specific corner case in which a key-value on a cache shard cannot be used. This happens when the key-value in the cache shard was written at a more recent database version than the version of the proxy database at that time. This would mean that the key-value probably has a different value than it had at the correct version. Because, in general, the cache shard and the proxy database versions are very close to each other, and this only happens for key-values that were written in between those two database versions, this happens very rarely. As such, deferring the lookup to storage nodes has no noticeable effect on the cache hit rate.</p>
    <div>
      <h3>Tiered Storage</h3>
      <a href="#tiered-storage">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2bLnTL9WWzQfMqjyXv5o6Q/1c1bf1cb348aa736fb320c77b52e10dd/image3.png" />
          </figure><p>To summarize, Quicksilver V2 has three levels of storage.</p><ol><li><p>Level 1: The local cache on each server that contains the key-values that have most recently been accessed.</p></li><li><p>Level 2: The data center wide sharded cache that contains key-values that haven’t been accessed in a while, but do have been accessed.</p></li><li><p>Level 3: The replicas on the storage nodes that contain the full dataset, which live on a handful of storage nodes and are only queried for the <i>cold</i> keys.</p></li></ol>
    <div>
      <h2>The results</h2>
      <a href="#the-results">
        
      </a>
    </div>
    <p>The percentage of keys that can be resolved within a data center improved significantly by adding the second caching layer. The worst performing instance has a cache hit rate higher than 99.99%. All other instances have a cache hit rate that is higher than 99.999%.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6V5BgOVPsTrYQf4WuUKdmg/67756312764cdab789eff1ff33caf0f3/image5.png" />
          </figure><p><sup>The combined level 1 and level 2 cache hit-rate is 99.99% or higher for the worst caching instance.</sup></p>
    <div>
      <h2>Final notes</h2>
      <a href="#final-notes">
        
      </a>
    </div>
    <p>It took the team quite a few years to go from the old Quicksilver V1, where all data was stored on each server to the tiered caching Quicksilver V2, where all but a handful of servers only have cache. We faced many challenges, including migrating hundreds of thousands of live databases without interruptions, while serving billions of requests per second. A lot of code changes were rolled out, with the result that Quicksilver now has a significantly different architecture. All of this was done transparently to our customers. It was all done iteratively, always learning from the previous step before taking the next one. And always making sure that, if at all possible, all changes are easy to revert. These are important strategies for migrating complex systems safely.</p><p>If you like these kinds of stories, keep an eye out for more development stories on our blog. And if you are enthusiastic about solving these kinds of problems, <a href="https://www.cloudflare.com/en-gb/careers/jobs/"><u>we are hiring for multiple types of roles across the organization</u></a></p>
    <div>
      <h2>Thank you</h2>
      <a href="#thank-you">
        
      </a>
    </div>
    <p>And finally, a big thanks to the rest of the Quicksilver team, because we all do this together: Aleksandr Matveev, Aleksei Surikov, Alex Dzyoba, Alexandra (Modi) Stana-Palade, Francois Stiennon, Geoffrey Plouviez, Ilya Polyakovskiy, Manzur Mukhitdinov, Volodymyr Dorokhov.</p> ]]></content:encoded>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Quicksilver]]></category>
            <category><![CDATA[Storage]]></category>
            <category><![CDATA[Key Value]]></category>
            <guid isPermaLink="false">5oxVTbLoVGabfWNbMtNbs</guid>
            <dc:creator>Marten van de Sanden</dc:creator>
            <dc:creator>Anton Dort-Golts</dc:creator>
        </item>
        <item>
            <title><![CDATA[Quicksilver v2: evolution of a globally distributed key-value store (Part 1)]]></title>
            <link>https://blog.cloudflare.com/quicksilver-v2-evolution-of-a-globally-distributed-key-value-store-part-1/</link>
            <pubDate>Thu, 10 Jul 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ This blog post is the first of a series, in which we share our journey in redesigning Quicksilver — Cloudflare’s distributed key-value store that serves over 3 billion keys per second globally.  ]]></description>
            <content:encoded><![CDATA[ <p>Quicksilver is a key-value store developed internally by Cloudflare to enable fast global replication and low-latency access on a planet scale. It was <a href="https://blog.cloudflare.com/introducing-quicksilver-configuration-distribution-at-internet-scale/"><u>initially designed</u></a> to be a global distribution system for configurations, but over time it gained popularity and became the foundational storage system for many products in Cloudflare.</p><p>A previous <a href="https://blog.cloudflare.com/moving-quicksilver-into-production/"><u>post</u></a> described how we moved Quicksilver to production and started replicating on all machines across our global network. That is what we called Quicksilver v1: each server has a full copy of the data and updates it through asynchronous replication. The design served us well for some time. However, as our business grew with an ever-expanding data center footprint and a growing dataset, it became more and more expensive to store everything everywhere.</p><p>We realized that storing the full dataset on every server is inefficient. Due to the uniform design, data accessed in one region or data center is replicated globally, even if it's never accessed elsewhere. This leads to wasted disk space. We decided to introduce a more efficient system with two new server roles: <b><i>replica</i></b>, which stores the full dataset and <b><i>proxy</i></b>, which acts as a persistent cache, evicting unused key-value pairs to free up some disk space. We call this design <b>Quicksilver v1.5</b> – an interim step towards a more sophisticated and scalable system.</p><p>To understand how those two roles helped us reduce disk space usage, we first need to share some background on our setup and introduce some terminology. Cloudflare is architected in a way where we have a few hyperscale core data centers that form our <a href="https://www.cloudflare.com/learning/network-layer/what-is-the-control-plane/"><u>control plane</u></a>, and many smaller data centers distributed across the globe where resources are more constrained. Quicksilver has dozens of servers in the core data centers with terabytes of storage called <b><i>root nodes</i></b>. In the smaller data centers, though, things are different. A typical data center has two types of nodes: <b><i>intermediate nodes </i></b><i>and </i><b><i>leaf nodes.</i></b> Intermediate servers replicate data either from the other intermediate nodes or directly from the root nodes. Leaf nodes serve end user traffic, and receive updates from intermediate servers, effectively being leaves of a replication tree. Disk capacity varies significantly between node types. While root nodes aren't facing an imminent disk space bottleneck, it's a definite concern for leaf nodes.</p><p>Every server – whether it’s a root, intermediate, or leaf – hosts 10 Quicksilver <b><i>instances</i></b>. These are independent databases, each used by specific Cloudflare services or products such as the <a href="https://www.cloudflare.com/application-services/products/dns/"><u>DNS</u></a>, <a href="https://www.cloudflare.com/application-services/products/cdn/"><u>CDN</u></a>  or <a href="https://www.cloudflare.com/application-services/products/waf/"><u>WAF</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/336Tl3Q00d5MVe29nzkQcY/3781ee725f2da6a847677235c1c3c960/image5.png" />
          </figure><p><sup>Figure 1. Global Quicksilver</sup></p><p>Let’s consider the role distribution. Instead of hosting ten full datasets on every machine within a data center, what if we deploy only a few replicas in each?  The remaining servers would be proxies, maintaining a persistent cache of hot keys and querying replicas for any cache misses.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3RzCZ7Yr1Nx3wd28DL5uco/5e4bd0cd0ce649080e77814ab6f048c0/image1.png" />
          </figure><p><sup>Figure 2. Role allocation for different Quicksilver instances</sup></p><p>Data centers across our network are very different in size, ranging from hundreds of servers to a single rack with just a few servers. To ensure every data center has at least one replica, the simplest initial step is an even split: on each server, place five replicas of some instances and five proxies for others. The change immediately frees up disk space, as the cached hot dataset on a proxy should be smaller than a full replica. While it doesn’t remove the bottleneck entirely, it could, in theory, lead to an up to 50% reduction in disk space usage. More importantly, it lays the foundation for a new distributed design of Quicksilver, where queries can be served by multiple machines in a data center, paving the way for further horizontal scaling. Additionally, an iterative approach helps to battle-proof the code changes earlier.</p>
    <div>
      <h2>Can it even work?</h2>
      <a href="#can-it-even-work">
        
      </a>
    </div>
    <p>Before committing to building Quicksilver v1.5, we wanted to be sure that the proxy/replica design would actually work for our workload. If proxies needed to cache the entire dataset for good performance, then it would be a dead end, offering no potential disk space benefits. To assess this, we built a data pipeline which pushes accessed keys from all across our network to <a href="https://clickhouse.com"><u>ClickHouse</u></a>. This allowed us to estimate typical sizes of working sets. Our analysis revealed that:</p><ul><li><p>in large data centers approximately, 20% of the keyspace was in use</p></li><li><p>in small data centers this number dropped to just about 1%</p></li></ul><p>These findings gave us confidence that the caching approach should work, though it wouldn’t be without its challenges.</p>
    <div>
      <h2>Persistent caching</h2>
      <a href="#persistent-caching">
        
      </a>
    </div>
    <p>When talking about caches, the first thing that comes to mind is an in-memory cache. However, this cannot work for Quicksilver for two main reasons: memory usage and the “cold cache” problem.</p><p>Indeed, with billions of stored keys, even a fraction of them would lead to an unmanageable increase in memory usage. System restarts should not affect performance, which means that cache data must be preserved somewhere anyway. So we decided to make the cache persistent and store it in the same way as full datasets: in our embedded <a href="https://rocksdb.org/"><u>RocksDB</u></a>. Thus, cached keys normally sit on disk and can be retrieved on-demand with low memory footprint.</p><p>When a key cannot be found in the proxy’s cache, we request it from a replica using our internal <i>distributed key-value protocol</i>, and put it into a local cache after processing.</p><p>Evictions are based on RocksDB <a href="https://github.com/facebook/rocksdb/wiki/Compaction-Filter"><u>compaction filters</u></a>. Compaction filters allow defining custom logic executed in background RocksDB threads responsible for compacting files on disk. Each key-value pair is processed with a filter on a regular basis, evicting least recently used data from the disk when available disk space drops below a certain threshold called a <i>soft limit</i>. To track keys accessed on disk, we have an LRU-like in-memory data structure, which is passed to the compaction filter to set last access date in key metadata and inform potential evictions.</p><p>However, with some specific workloads there is still a chance that evictions will not keep up with disk space growth, and for this scenario we have a <i>hard limit</i>: when available disk space drops below a critical threshold, we temporarily stop adding new keys to the cache. This hurts performance, but it acts as a safeguard, ensuring our proxies remain stable and don't overflow under a massive surge of requests.</p>
    <div>
      <h2>Consistency and asynchronous replication</h2>
      <a href="#consistency-and-asynchronous-replication">
        
      </a>
    </div>
    <p>Quicksilver has, from the start, provided <a href="https://jepsen.io/consistency/models/sequential"><u>sequential consistency</u></a> to clients: if key A was written before B, it’s not possible to read B and not A. We are committed to maintaining this guarantee in the new design. We have experienced <a href="https://www.hyrumslaw.com/"><u>Hyrum's Law</u></a> first hand, with Quicksilver being so widely adopted across the company that every property we introduced in earlier versions is now relied upon by other teams. This means that changing behaviour would inevitably break existing functionality and introduce bugs.</p><p>However, there is one thing standing in our way: asynchronous replication. Quicksilver replication is asynchronous mainly because machines in different parts of the world replicate at different speeds, and we don’t want a single server to slow down the entire tree. But it turns out in a proxy-replica design, independent replication progress can result in non-<a href="https://jepsen.io/consistency/models/monotonic-reads"><u>monotonic</u></a> reads!</p><p>Consider the following scenario: a client sequentially writes keys A, B, C, .. K one after another to the Quicksilver root node. These keys are asynchronously replicated through data centers across our network with varying latency. Imagine we have a proxy on index 5, which has observed keys from A to E, and two replicas: </p><ul><li><p>replica_1 is at index 2 (slightly behind the proxy), having only received A and B</p></li><li><p>replica_2 at index 9, which is slightly ahead due to a faster replication path and has received all keys from A to I
</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3miaQrw1UCUypXhra7mada/e713ebf0299e4b6f0a15bb25bbfa451a/image6.jpg" />
          </figure></li></ul><p><sup>Figure 3. Asynchronous replication in QSv1.5</sup></p><p>Now, a client performs two successive requests on a proxy, each time reading the keys E, F, G, H and I. For simplicity, we assume these keys are not cacheable (for example, due to low disk space). The proxy’s first remote request is routed to replica_2, which already has all keys and responds back with values. To prevent hot spots in a data center, we load balance requests from proxies, and the next one lands on replica_1, which hasn’t received any of the requested keys yet, and responds with a “not found” error.</p><p>So, which result is correct?</p><p>The correct behavior here is that of Quicksilver v1, which we aim to preserve. If the server on replication index 5 were a replica instead of a proxy, it would have seen updates for keys A through E inclusive, resulting in E being the only key in both replies, while all other keys cannot be found yet. Which means <i>responses from both replica_1 and replica_2 are wrong!</i></p><p>Therefore, to maintain previous guarantees and API backwards compatibility, Quicksilver v1.5 must address two crucial consistency problems: cases where the replica is ahead of the proxy, and conversely, where it lags behind. For now let’s focus on the case where a proxy lags behind a replica.</p>
    <div>
      <h2>Multiversion concurrency control</h2>
      <a href="#multiversion-concurrency-control">
        
      </a>
    </div>
    <p>In our example, replica_2 responds to a request from a proxy “from the past”. We cannot use any locks for synchronizing two servers, as it would introduce undesirable delays to the replication tree, defeating the purpose of asynchronous replication. The only option is for replicas to maintain a history of recent updates. This naturally leads us to implementing <b>multiversion concurrency control </b>(<a href="https://en.wikipedia.org/wiki/Multiversion_concurrency_control"><u>MVCC</u></a>), a popular database mechanism for tracking changes in a non-blocking fashion, where for any key we can keep multiple versions of its values for different points in time.</p><p>With MVCC, we no longer overwrite the latest value of a key in the default <a href="https://github.com/facebook/rocksdb/wiki/column-families"><u>column family</u></a> for every update. Instead, we introduced a new MVCC column family in RocksDB, where all updates are stored with a corresponding replication index. Lookup for a key at some index in the past goes as follows:</p><ol><li><p>First we search in the default column family. If a key is found and the write timestamp is not greater than the index of a requesting proxy, we can use it straight away.</p></li><li><p>Otherwise, we begin scanning the MVCC column family, where keys have unique suffixes based on latest timestamps for which they are still valid.</p></li></ol><p>In the example above, replica_2 has MVCC enabled and has keys A@1 .. K@11 in its default column family. The MVCC is initially empty, because no keys have been overwritten yet. When it receives a request for, say, key H with target index 5, it first makes a lookup in a default column family and finds the given key, but its timestamp is 8, which means this version should not be visible to the proxy yet. It then scans the MVCC, finds no matching previous versions and responds with “not found” to the proxy. Should key H be updated twice at indexes 4 and 8, we would have placed the initial version into MVCC before overwriting it in the default column family, and the proxy would receive the first version in response.</p><p>If a key E is requested at index 5, replica_2 can find it quickly in the default column family and return it back to the proxy. There is no need to read from MVCC, as the timestamp of the latest version (5) satisfies the request.</p><p>Another corner case to consider is deletions. When a key is deleted and then re-written, we need to explicitly mark the period of removal in MVCC. For that we’ve implemented <a href="https://en.wikipedia.org/wiki/Tombstone_(data_store)"><u>tombstones</u></a> – a special value format for absent keys.</p><p>Finally, we need to make sure that key history is not growing uncontrollably, using up all of the disk space available. Luckily we don’t actually need to record history for a long period of time, it just needs to cover the maximum replication index difference between any two machines. And in practice, a two-hour interval turned out to be way more than enough, while adding only about 500 MB of extra disk space usage. All records in the MVCC column family older than two hours are garbage collected, and for that again we use custom RocksDB compaction filters.</p>
    <div>
      <h2>Sliding window</h2>
      <a href="#sliding-window">
        
      </a>
    </div>
    <p>Now we know how to deal with proxies lagging behind replicas. But what about the opposite case, when a proxy is ahead of replicas?</p><p>The simplest solution is for replicas to not serve requests with a target index higher than its own. After all, it cannot know about keys from the future, whether they will be added, updated, or removed. In fact, our first implementation just returned an error when the proxy was ahead, as we expected it to happen quite infrequently. But after rolling out gradually to a few data centers, our metrics made it clear that the approach was not going to work.</p><p>This led us to analyze which keys are affected by this kind of replication asymmetry. It’s definitely not keys added or updated a long time ago, because replicas would already have the changes replicated. The only problematic keys are those updated very recently, which the proxy already knows about, but the replica does not.</p><p>With this insight, we realized that the issue should be solved on the proxies rather than on the replica side. By preserving <i>all</i> recent updates locally, the proxy can avoid querying the replica. This became known as the <b>sliding window</b> approach.</p><p>The sliding window retains all recent updates written in a short, rolling timeframe. Unlike cached keys, items in the window cannot be evicted until they move outside of the window. Internally, the sliding window is defined by lower and upper boundary pointers. These are kept in memory, and can easily be restored after a reload from the current database index and the pre-configured window size.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3kj7NdphFy8BQoJmsRH8fH/37ca06ac1c1800e4e97073815e754e51/image4.jpg" />
          </figure><p><sup>Figure 4. The sliding window shifts when replication updates arrive</sup></p><p>When a new update event arrives from the replication layer we add it to the sliding window by moving both the upper and lower boundary one position higher. Thereby, we maintain the fixed size of the window. Keys written before the lower bound can be evicted by the compaction filter, which is aware of current sliding window boundaries.</p>
    <div>
      <h2>Negative lookups</h2>
      <a href="#negative-lookups">
        
      </a>
    </div>
    <p>Another problem arising with our distributed replica-proxy design is negative lookups – requests for keys which don't exist in the database. Interestingly, in our workloads we see about ten times more negative lookups than positive ones!</p><p>But why is it a problem? Unfortunately, each negative lookup will be a cache miss on a proxy, requiring a request to a replica. Given the volume of requests and proportion of such lookups, it would be a disaster for performance, with overloaded replicas, overused data center networks, and massive latency degradation. We needed a fast and efficient approach to identifying non-existing keys directly at the proxy level.</p><p>In v1, negative lookups are the quickest type of requests. We rely on a special probabilistic data structure – <a href="https://en.wikipedia.org/wiki/Bloom_filter"><u>Bloom filters</u></a> – used in RocksDB to determine if the requested key might belong to a certain data file containing a range of sorted keys (called Sorted Sequence Table or SST) or definitely not. 99% of the time, negative lookups are served using only this in-memory data structure, avoiding the need for disk I/O.</p><p>One approach we considered for proxies was to cache negative lookups. Two problems immediately arise:</p><ul><li><p>How big is the keyspace of negative lookups? In theory, it’s infinite, but the real size was unclear. We can store it in our cache only if it is small enough.</p></li><li><p>Cached negative lookups would no longer be served by the fast Bloom filters. We have row and block caches in RocksDB, but the hit rate is nowhere near the filters for SSTs, which means negative lookups would end up going to disk more often.</p></li></ul><p>These turned out to be dealbreakers: not only was the negative keyspace vast, greatly exceeding the actual keyspace (by a thousand times for some instances!), but clients also need lookups to be <i>really</i> fast, ideally served from memory.</p><p>In pursuit of probabilistic data structures which could give us a dynamic compact representation of a full keyspace on proxies, we spent some time exploring <a href="https://en.wikipedia.org/wiki/Cuckoo_filter"><u>Cuckoo filters</u></a>. Unfortunately, with 5 billion keys it takes about 18 GB to have a false positive rate similar to Bloom filters (which only require 6 GB). And this is not only about wasted disk space — to be fast we have to keep it all in memory too!</p><p>Clearly some other solution was needed.</p><p>Finally, we decided to implement <b>key and value separation</b>, storing all keys on proxies, but persisting values only for cached keys. Evicting a key from the cache actually results in the removal of its value.</p><p>But wait, don’t the keys, even stripped of values, take a lot of space? Well, yes and no.</p><p>The total size of pure keys in Quicksilver is approximately 11 times smaller than the full dataset. Of course, it’s larger than any representation by probabilistic data structure, but there are some very desirable properties to such a solution. Firstly, we continue to enjoy fast Bloom filter lookups in RocksDB. Another benefit is that it unlocks some cool optimizations for range queries in a distributed context.</p><p>We may revisit it one day, but so far it has worked great for us.</p>
    <div>
      <h2>Discovery mechanism</h2>
      <a href="#discovery-mechanism">
        
      </a>
    </div>
    <p>Having solved all of the above challenges, one bit remained to be sorted out to make distributed query execution work: how can proxies discover replicas?</p><p>Within the local data center it is fairly easy. Each one runs its own <a href="https://www.consul.io/"><u>consul</u></a> cluster, where machines are registered as services. Consul is well integrated with our internal DNS resolvers, and with a single DNS request, we can get the names of all replicas running in a data center, which proxies can directly connect to.</p><p>However, data centers vary in size, servers are constantly added and removed, and having only local discovery would not be enough for the system to work reliably. Proxies also need to find replicas in other nearby data centers.</p><p>We had previously encountered a similar problem with our replication layer. Initially, the replication topology was statically defined in a configuration and distributed to all servers, such that they know from which sources they should replicate. While simple, this approach was quite fragile and tedious to operate. It led to a rigid replication tree with suboptimal overall performance, unable to adapt to network changes.</p><p>Our solution to this problem was the <b>Network Oracle</b> – a special overlay network based on a <a href="https://en.wikipedia.org/wiki/Gossip_protocol"><u>gossip</u></a> protocol and consisting of intermediate nodes in our data centers. Each member of this overlay constantly exchanges status and metainformation with other nodes, which helps us see active members in near-real time. Each member runs network probes measuring round-trip time to its peers, making it easy to find closest (in terms of <a href="https://www.cloudflare.com/learning/cdn/glossary/round-trip-time-rtt/"><u>RTT</u></a>) active intermediate nodes to form a low-latency replication tree. Introducing the Network Oracle was a major improvement: we no longer needed to reconfigure the topology, watch intermediate nodes or entire data centers go down, or investigate frequent replication issues. Replication is now a completely self-organized and self-healing dynamic system.</p><p>Naturally, we decided to reuse the Network Oracle for our discovery mechanism. It consists of two subproblems: data center discovery and specific service lookup. We use the Network Oracle to find the closest data centers. Adding all machines running Quicksilver to the same overlay would be inefficient because of significant increase of network traffic and message delivery times. Instead, we use intermediate nodes as sources of <b>network proximity</b> information for the leaf nodes. Knowing which data centers are nearby, we can directly send DNS queries there to resolve specific services – Quicksilver replicas in this case.</p><p>Proxies maintain a pool of connections to active replicas and distribute requests among them to smooth out the load and avoid hotspots in a data center. Proxies also have a health-tracking mechanism, monitoring the state of connections and errors coming from replicas, and temporarily deprioritizing or isolating potentially faulty ones.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/70olkvpfiCY3aDNn1owv1j/a188c0b9253c0e23f0341463a31b5f8e/image3.png" />
          </figure><p><sup>Figure 5. Internal replica request errors</sup></p><p>To demonstrate its efficiency, we graphed errors coming from replica requests, which showed that such errors almost disappeared after introducing the new discovery system.</p>
    <div>
      <h2>Results</h2>
      <a href="#results">
        
      </a>
    </div>
    <p>Our objective with Quicksilver v1.5 was simple: gain some disk space without losing request latency, because clients rely heavily on us being fast. While the replica-proxy design delivered significant space savings, what about latencies?</p><p>Proxy</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/jyrzamGb5K05r7EOSJbrq/05a30c951ad2c9c91edd72f898bd09f1/image7.png" />
          </figure><p>Replica</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ry4erxQ6vf7WF6wSfPpit/0de9d46bbdb4a69f2d210ec6c8baadcd/image2.png" />
          </figure><p><sup>Figure 6. Proxy-replica latency comparison</sup></p><p>Above, we have the 99.9% percentile of request latency on both a replica and proxy during a 24-hour window. One can hardly find a difference between the two. Surprisingly, proxies can even be slightly faster than replicas sometimes, likely because of smaller datasets on disk!</p><p>Quicksilver v1.5 is released but our journey to a highly scalable and efficient solution is not over. In the next post we’ll share what challenges we faced with the following iteration. Stay tuned!</p>
    <div>
      <h2>Thank you</h2>
      <a href="#thank-you">
        
      </a>
    </div>
    <p>This project was a big team effort, so we’d like to thank everyone on the Quicksilver team – it would not have come true without you all.</p><ul><li><p>Aleksandr Matveev</p></li><li><p>Aleksei Surikov</p></li><li><p>Alex Dzyoba</p></li><li><p>Alexandra (Modi) Stana-Palade</p></li><li><p>Francois Stiennon</p></li><li><p>Geoffrey Plouviez</p></li><li><p>Ilya Polyakovskiy</p></li><li><p>Manzur Mukhitdinov</p></li><li><p>Volodymyr Dorokhov</p></li></ul><p></p> ]]></content:encoded>
            <category><![CDATA[Quicksilver]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[RocksDB]]></category>
            <category><![CDATA[Storage]]></category>
            <category><![CDATA[Replication]]></category>
            <category><![CDATA[Distributed]]></category>
            <guid isPermaLink="false">4gVdi0wvV700DVpfnnBo7j</guid>
            <dc:creator>Anton Dort-Golts</dc:creator>
            <dc:creator>Marten van de Sanden</dc:creator>
        </item>
        <item>
            <title><![CDATA[“You get Instant Purge, and you get Instant Purge!” — all purge methods now available to all customers]]></title>
            <link>https://blog.cloudflare.com/instant-purge-for-all/</link>
            <pubDate>Tue, 01 Apr 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Following up on having the fastest purge in the industry, we have now increased Instant Purge quotas across all Cloudflare plans.  ]]></description>
            <content:encoded><![CDATA[ <p>There's a tradition at Cloudflare of launching real products on April 1, instead of the usual joke product announcements circulating online today. In previous years, we've introduced impactful products like <a href="https://blog.cloudflare.com/announcing-1111/"><u>1.1.1.1</u></a> and <a href="https://blog.cloudflare.com/introducing-1-1-1-1-for-families/"><u>1.1.1.1 for Families</u></a>. Today, we're excited to continue this tradition by <b>making every purge method available to all customers, regardless of plan type.</b></p><p>During Birthday Week 2024, we <a href="https://blog.cloudflare.com/instant-purge/"><u>announced our intention</u></a> to bring the full suite of purge methods — including purge by URL, purge by hostname, purge by tag, purge by prefix, and purge everything — to all Cloudflare plans. Historically, methods other than "purge by URL" and "purge everything" were exclusive to Enterprise customers. However, we've been openly rebuilding our purge pipeline over the past few years (hopefully you’ve read <a href="https://blog.cloudflare.com/part1-coreless-purge/"><u>some of our</u></a> <a href="https://blog.cloudflare.com/rethinking-cache-purge-architecture/"><u>blog</u></a> <a href="https://blog.cloudflare.com/instant-purge/"><u>series</u></a>), and we're thrilled to share the results more broadly. We've spent recent months ensuring the new Instant Purge pipeline performs consistently under 150 ms, even during increased load scenarios, making it ready for every customer.  </p><p>But that's not all — we're also significantly raising the default purge rate limits for Enterprise customers, allowing even greater purge throughput thanks to the efficiency of our newly developed <a href="https://blog.cloudflare.com/instant-purge/"><u>Instant Purge</u></a> system.</p>
    <div>
      <h2>Building a better purge: a two-year journey</h2>
      <a href="#building-a-better-purge-a-two-year-journey">
        
      </a>
    </div>
    <p>Stepping back, today's announcement represents roughly two years of focused engineering. Near the end of 2022, our team went heads down rebuilding Cloudflare’s purge pipeline with a clear yet challenging goal: dramatically increase our throughput while maintaining near-instant invalidation across our global network.</p><p>Cloudflare operates <a href="https://www.cloudflare.com/network"><u>data centers in over 335 cities worldwide</u></a>. Popular cached assets can reside across all of our data centers, meaning each purge request must quickly propagate to every location caching that content. Upon receiving a purge command, each data center must efficiently locate and invalidate cached content, preventing stale responses from being served. The amount of content that must be invalidated can vary drastically, from a single file, to all cached assets associated with a particular hostname. After the content has been purged, any subsequent requests will trigger retrieval of a fresh copy from the origin server, which will be stored in Cloudflare’s cache during the response. </p><p>Ensuring consistent, rapid propagation of purge requests across a vast network introduces substantial technical challenges, especially when accounting for occasional data center outages, maintenance, or network interruptions. Maintaining consistency under these conditions requires robust distributed systems engineering.</p>
    <div>
      <h2>How did we scale purge?</h2>
      <a href="#how-did-we-scale-purge">
        
      </a>
    </div>
    <p>We've <a href="https://blog.cloudflare.com/instant-purge/"><u>previously discussed</u></a> how our new Instant Purge system was architected to achieve sub-150 ms purge times. It’s worth noting that the performance improvements were only part of what our new architecture achieved, as it also helped us solve significant scaling challenges around storage and throughput that allowed us to bring Instant Purge to all users. </p><p>Initially, our purge system scaled well, but with rapid customer growth, the storage consumption from millions of daily purge keys that needed to be stored reduced available caching space. Early attempts to manage this storage and throughput demand involved <a href="https://www.boltic.io/blog/kafka-queue"><u>queues</u></a> and batching for smoothing traffic spikes, but this introduced latency and underscored the tight coupling between increased usage and rising storage costs.</p><p>We needed to revisit our thinking on how to better store purge keys and when to remove purged content so we could reclaim space. Historically, when a customer would purge by tag, prefix or hostname, Cloudflare would mark the content as expired and allow it to be evicted later. This is known as lazy-purge because nothing is actively removed from disk. Lazy-purge is fast, but not necessarily efficient, because it consumes storage for expired but not-yet-evicted content. After examining global or data center-level indexing for purge keys, we decided that wasn't viable due to increases in system complexity and the latency those indices could bring due to our network size. So instead, we opted for per-machine indexing, integrating indices directly alongside our cache proxies. This minimized network complexity, simplified reliability, and provided predictable scaling.</p><p>After careful analysis and benchmarking, we selected <a href="https://rocksdb.org/"><u>RocksDB</u></a>, an embedded key-value store that we could optimize for our needs, which formed the basis of <a href="https://blog.cloudflare.com/instant-purge/#putting-it-all-together"><u>CacheDB</u></a>, our Rust-based service running alongside each cache proxy. CacheDB manages indexing and immediate purge execution (active purge), significantly reducing storage needs and freeing space for caching.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4FZ0bQSx5MUhx3x3hwlRuk/91a27af7db5e629cd6d5fbe692397eaf/image2.png" />
          </figure><p>Local queues within CacheDB buffer purge operations to ensure consistent throughput without latency spikes, while the cache proxies consult CacheDB to guarantee rapid, active purges. Our updated distribution pipeline broadcasts purges directly to CacheDB instances across machines, dramatically improving throughput and purge speed.</p><p>Using CacheDB, we've reduced storage requirements 10x by eliminating lazy purge storage accumulation, instantly freeing valuable disk space. The freed storage enhances cache retention, boosting cache HIT ratios and minimizing origin egress. These savings in storage and increased throughput allowed us to scale to the point where we can offer Instant Purge to more customers.</p><p>For more information on how we designed the new Instant Purge system, please see the previous <a href="https://blog.cloudflare.com/instant-purge/"><u>installment</u></a> of our Purge series blog posts. </p>
    <div>
      <h2>Striking the right balance: what to purge and when</h2>
      <a href="#striking-the-right-balance-what-to-purge-and-when">
        
      </a>
    </div>
    <p>Moving on to practical considerations of using these new purge methods, it’s important to use the right method for what you want to invalidate. Purging too aggressively can overwhelm origin servers with unnecessary requests, driving up egress costs and potentially causing downtime. Conversely, insufficient purging leaves visitors with outdated content. Balancing precision and speed is vital.</p><p>Cloudflare supports multiple targeted purge methods to help customers achieve this balance.</p><ul><li><p><a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/"><b><u>Purge Everything</u></b></a>: Clears all cached content associated with a website.</p></li><li><p><a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge_by_prefix/"><b><u>Purge by Prefix</u></b></a>: Targets URLs sharing a common prefix.</p></li><li><p><a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-hostname/"><b><u>Purge by Hostname</u></b></a>: Invalidates content by specific hostnames.</p></li><li><p><a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-single-file/"><b><u>Purge by URL (single-file purge</u></b></a><b>)</b>: Precisely targets individual URLs.</p></li><li><p><a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/"><b><u>Purge by Tag</u></b></a>: Uses <a href="https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/#add-cache-tag-http-response-headers"><u>Cache-Tag</u></a> headers to invalidate grouped assets, offering flexibility for complex cache management scenarios.</p></li></ul><p>Starting today, all of these methods are available to every Cloudflare customer.    </p>
    <div>
      <h2>How to purge </h2>
      <a href="#how-to-purge">
        
      </a>
    </div>
    <p>Users can select their purge method directly in the Cloudflare dashboard, located under the Cache tab in the <a href="https://dash.cloudflare.com/?to=/:account/:zone/caching/configuration"><u>configurations section</u></a>, or via the <a href="https://developers.cloudflare.com/api/resources/cache/"><u>Cloudflare API</u></a>. Each purge request should clearly specify the targeted URLs, hostnames, prefixes, or cache tags relevant to the selected purge type (known as purge keys). For instance, a prefix purge request might specify a directory such as example.com/foo/bar. To maximize efficiency and throughput, batching multiple purge keys in a single request is recommended over sending individual purge requests each with a single key.</p>
    <div>
      <h2>How much can you purge?</h2>
      <a href="#how-much-can-you-purge">
        
      </a>
    </div>
    <p>The new rate limits for Cloudflare's purge by tag, prefix, hostname, and purge everything are different for each plan type. We use a <a href="https://en.wikipedia.org/wiki/Token_bucket"><u>token bucket</u></a> rate limit system, so each account has a token bucket with a maximum size based on plan type. When we receive a purge request we first add tokens to the account’s bucket based on the time passed since the account’s last purge request divided by the refill rate for its plan type (which can be a fraction of a token). Then we check if there’s at least one whole token in the bucket, and if so we remove it and process the purge request. If not, the purge request will be rate limited. An easy way to think about this rate limit is that the refill rate represents the consistent rate of requests a user can send in a given period while the bucket size represents the maximum burst of requests available.</p><p>For example, a free user starts with a bucket size of 25 requests and a refill rate of 5 requests per minute (one request per 12 seconds). If the user were to send 26 requests all at once, the first 25 would be processed, but the last request would be rate limited. They would need to wait 12 seconds and retry their last request for it to succeed. </p><p>The current limits are applied per <b>account</b>: </p><table><tr><td><p><b>Plan</b></p></td><td><p><b>Bucket size</b></p></td><td><p><b>Request refill rate</b></p></td><td><p><b>Max keys per request</b></p></td><td><p><b>Total keys</b></p></td></tr><tr><td><p><b>Free</b></p></td><td><p>25 requests</p></td><td><p>5 per minute</p></td><td><p>100</p></td><td><p>500 per minute</p></td></tr><tr><td><p><b>Pro</b></p></td><td><p>25 requests</p></td><td><p>5 per second</p></td><td><p>100</p></td><td><p>500 per second</p></td></tr><tr><td><p><b>Biz</b></p></td><td><p>50 requests</p></td><td><p>10 per second</p></td><td><p>100</p></td><td><p>1,000 per second</p></td></tr><tr><td><p><b>Enterprise</b></p></td><td><p>500 requests</p></td><td><p>50 per second</p></td><td><p>100</p></td><td><p>5,000 per second</p></td></tr></table><p>More detailed documentation on all purge rate limits can be found in our <a href="https://developers.cloudflare.com/cache/how-to/purge-cache/"><u>documentation</u></a>.</p>
    <div>
      <h2>What’s next?</h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>We’ve spent a lot of time optimizing our purge platform. But we’re not done yet. Looking forward, we will continue to enhance the performance of Cloudflare’s single-file purge. The current P50 performance is around 250 ms, and we suspect that we can optimize it further to bring it under 200 ms. We will also build out our ability to allow for greater purge throughput for all of our systems, and will continue to find ways to implement filtering techniques to ensure we can continue to scale effectively and allow customers to purge whatever and whenever they choose. </p><p>We invite you to try out our new purge system today and deliver an instant, seamless experience to your visitors.</p> ]]></content:encoded>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Cache Purge]]></category>
            <guid isPermaLink="false">4LTq8Utw6K58W4ojKxsqw8</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator> Connor Harwood</dc:creator>
            <dc:creator>Zaidoon Abd Al Hadi</dc:creator>
        </item>
        <item>
            <title><![CDATA[Sometimes I cache: implementing lock-free probabilistic caching]]></title>
            <link>https://blog.cloudflare.com/sometimes-i-cache/</link>
            <pubDate>Thu, 26 Dec 2024 14:00:00 GMT</pubDate>
            <description><![CDATA[ If you want to know what cache revalidation is, how it works, and why it can involve rolling a die, read on. This blog post presents a lock-free probabilistic approach to cache revalidation, along 
 ]]></description>
            <content:encoded><![CDATA[ <p>HTTP caching is conceptually simple: if the response to a request is in the cache, serve it, and if not, pull it from your origin, put it in the cache, and return it. When the response is old, you repeat the process. This is called cache revalidation. If you are worried about too many requests going to your origin at once, you protect it with a <a href="https://developers.cloudflare.com/cache/concepts/revalidation/"><u>cache lock</u></a>: a small program, possibly distinct from your cache, that indicates if a request is already going to your origin. This is called request collapsing.</p><p>In this blog post, we dive into how cache revalidation works, and present a new approach based on probability. For every request going to the origin, we simulate a die roll. If it’s 6, the request can go to the origin. Otherwise, it stays stale to protect our origin from being overloaded. To see how this is built and optimised, read on.</p>
    <div>
      <h2>Background</h2>
      <a href="#background">
        
      </a>
    </div>
    <p>Let's take the example of an online image library. When a client requests an image, the service first checks its cache to see if the resource is present. If it is, it returns it. If it is not, the image server processes the request, places the response into the cache for a day, and returns it. When the cache expires, the process is repeated.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6zdgMhKkU3cVKRk9T2CO2I/5302e6ef68cabd04b8bd65a7e416f033/BLOG-2639_2.png" />
          </figure><p><i>Figure 1: Uncached request goes to the origin</i></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4J5KIW2CocyvlLXLuVBTWH/1f6174983e1fc1de72b48a9801da160e/BLOG-2639_3.png" />
          </figure><p><i>Figure 2: Cached request stops at the cache</i></p><p>And this is where things get complex. The image of a cat might be quite popular. Let's say it's requested 10 times per second. Let’s also assume the image server cannot handle more than 1 request per second. After a day, the cache expires. 10 requests hit the service. Given there are no up-to-date items in cache, these 10 requests are going to go directly to the image server. This problem is known as <a href="https://en.wikipedia.org/wiki/Cache_stampede"><u>cache stampede</u></a>. When the image server sees these 10 requests all happening at the same time, it gets overloaded.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3xDMJ6iloIjNHWpAbkfXWv/bee11bc4e1bb83a5b330529d8d98fbaa/BLOG-2639_4.png" />
          </figure><p><i>Figure 3: Image server overloaded upon cache expiration. This can happen to one or multiple users, across locations.</i></p><p>This all stops if the cache gets populated, as it can handle a lot more requests than the origin.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7LVi2SItiAUYWdEm3ll3ZH/368c6ff8e5d9017d2d3a8cc96246b73c/BLOG-2639_5.png" />
          </figure><p><i>Figure 4: Cache is populated and can handle the load. The image server is healthy again.</i></p><p>In the following sections, we build this image service, see how it can prevent cache stampede with a cache lock, then dive into probabilistic cache revalidation, and its optimisation.</p>
    <div>
      <h2>Setup</h2>
      <a href="#setup">
        
      </a>
    </div>
    <p>Let's write this image service. We need an image, a server, and a cache. For the image we're going to use a picture of <a href="https://files.research.cloudflare.com/images/cat.jpg"><u>my cat</u></a>, Cloudflare Workers for the server, and the Cloudflare Cache API for caching.</p><p>Note to the reader: On purpose, we aren’t using <a href="https://developers.cloudflare.com/kv/"><u>Cloudflare KV</u></a> or <a href="https://developers.cloudflare.com/cache/"><u>Cloudflare CDN Cache</u></a>, because they already solve our cache validation problem by using a cache lock.</p>
            <pre><code>let cache = caches.default
const CACHE_KEY = new Request('https://cache.local/')
const CACHE_AGE_IN_S = 86_400 // 1 day

function cacheExpirationDate() {
  return new Date(Date.now() + 1000*CACHE_AGE_IN_S)
}

function fetchAndCache(ctx) {
  let response = await fetch('https://files.research.cloudflare.com/images/cat.jpg')
  response = new Response(
	await response.arrayBuffer(),
	{
  	  headers: {
  	    'Content-Type': response.headers.get('Content-Type'),
  	    'Expires': cacheExpirationDate().toUTCString(),
  	  },
	},
  )
  ctx.waitUntil(cache.put(CACHE_KEY, response.clone()))
  return response
}

export default {
  async fetch(request, env, ctx) {
	let cachedResponse = await cache.match(CACHE_KEY)
	if (cachedResponse) {
  	  return cachedResponse
	}
	return fetchAndCache(ctx)
  }
}</code></pre>
            <p><i>Codeblock 1: Image server with a non-collapsing cache</i></p>
    <div>
      <h2>Expectation about cache revalidation</h2>
      <a href="#expectation-about-cache-revalidation">
        
      </a>
    </div>
    <p>The image service is receiving 10 requests per second, and it caches images for a day. It's reasonable to assume we would like to start revalidating the cache 5 minutes before it expires. The code evolves as follows:</p>
            <pre><code>let cache = caches.default
const CACHE_KEY = new Request('https://cache.local/')
const CACHE_AGE_IN_S = 86_400 // 1 day
const CACHE_REVALIDATION_INTERVAL_IN_S = 300

function cacheExpirationDate() {
  // Date constructor in workers takes Unix time in milliseconds
  // Date.now() returns time in milliseconds as well
  return new Date(Date.now() + 1000*CACHE_AGE_IN_S)
}

async function fetchAndCache(ctx) {
  let response = await fetch('https://files.research.cloudflare.com/images/cat.jpg')
  response = new Response(
	await response.arrayBuffer(),
	{
  	  headers: {
  	    'Content-Type': response.headers.get('Content-Type'),
  	    'Expires': cacheExpirationDate().toUTCString(),
  	  },
	},
  )
  ctx.waitUntil(cache.put(CACHE_KEY, response.clone()))
  return response
}

// Revalidation function added here
// This is were we are going to focus our effort: should the request be revalidated ?
function shouldRevalidate(expirationDate) {
  let remainingCacheTimeInS = (expirationDate.getTime() - Date.now()) / 1000

  return remainingCacheTimeInS &lt;= CACHE_REVALIDATION_INTERVAL_IN_S
}

export default {
  async fetch(request, env, ctx) {
	let cachedResponse = await cache.match(CACHE_KEY)
	if (cachedResponse) {
       // revalidation happens only if the request was cached. Otherwise, the resource is fetched anyway
  	  if (shouldRevalidate()) {
    	    ctx.waitUntil(fetchAndCache(ctx))
  	  }
  	  return cachedResponse
	}
	return fetchAndCache(ctx)
  }
}</code></pre>
            <p><i>Codeblock 2: Image server with early-revalidation and a non-collapsing cache</i></p><p>That code works, and we can now revalidate 5 minutes in advance of cache expiration. However, instead of fetching the image from the origin server at expiration time, all requests are going to be made 5 minutes in advance, and that does not solve our cache stampede problem. This happens no matter if requests are coming to a single location or not, given the code above does not collapse requests.</p><p>To solve our cache stampede problem, we need the revalidation process to not send too many requests at the same time. Ideally, we would like only one request to be sent between <code>expiration - 5min</code> and <code>expiration</code>.</p>
    <div>
      <h2>The usual solution: a cache lock</h2>
      <a href="#the-usual-solution-a-cache-lock">
        
      </a>
    </div>
    <p>To make sure there is only one request at a time going to the origin server, the solution that's usually deployed is a cache lock. The idea is that for a specific item, a cat picture in our case, requests to the origin try to obtain a lock. The request obtaining the lock can go to the origin, the others will serve stale content.</p><p>The lock has two methods: <code>try_lock</code> and <code>unlock</code>.</p><ul><li><p><code>try_lock</code> if the lock is free, take it and return <code>true</code>. If not, return <code>false</code>.</p></li><li><p><code>unlock</code> releases the lock.</p></li></ul><p>Such a lock can be implemented as a <a href="https://developers.cloudflare.com/workers/runtime-apis/rpc/"><u>Cloudflare RPC service</u></a>:</p>
            <pre><code>import { WorkerEntrypoint } from 'cloudflare:workers'

class Lock extends WorkerEntryPoint {
  async try_lock(key) {
	let value = await this.ctx.storage.get(key)
	if (!value) {
  	  await this.ctx.storage.put(key, true)
  	  return true
	}
	return false
  }

  unlock() {
	return this.ctx.storage.delete(key)
  }
}
</code></pre>
            <p><i>Codeblock 3: Lock service implemented with a Durable Object</i></p><p>That service can then be used as a cache lock.</p>
            <pre><code>// CACHE_LOCK is an instantiation of the above binding
// Assuming the above is deployed as a worker with name `lock`
// It can be bound in wrangler.toml as follows
// services = [ { binding = "CACHE_LOCK", service = "lock" } ]

const LOCK_KEY = "cat_image_service"

async function fetchAndCache(env, ctx) {
  let response = await fetch('...')
  ctx.waitUntil(env.CACHE_LOCK.unlock(LOCK_KEY))
  ...
}

function shouldRevalidate(env, expirationDate) {
  let remainingCacheTimeInS = (expirationDate.getTime() - Date.now()) / 1000

  // check if the expiry window is now, and then if the revalidation lock is available. if it is, take it
  return remainingCacheTimeInS &lt;= CACHE_REVALIDATION_INTERVAL_IN_S &amp;&amp; env.CACHE_LOCK.try_lock(LOCK_KEY)
}
</code></pre>
            <p><i>Codeblock 4: Image server with early-revalidation and a cache using a cache-lock</i></p><p>Now you might say "Et voilà. No need for probabilities and mathematics. Peak engineering has triumphed." And you might be right, in most cases. That's why cache locks are so <a href="https://developers.cloudflare.com/cache/concepts/revalidation/"><u>predominant</u></a>: they are conceptually simple, deterministic for the same key, and scale well with predictable resource usage.</p><p>On the other hand, cache locks add latency and fallibility. To take ownership of a lock, cache revalidation has to contact the lock service. This service is shared across different processes, possibly different machines in different locations. Requests therefore take time. In addition, this service might be unavailable. Probabilistic cache revalidation does not suffer from these, given it does not reach out to an external service but rolls a die with the local randomness generator. It does so at the cost of not guaranteeing the number of requests going to the origin server: maybe zero for an extended period, maybe more than one. On average, this is going to be fine. But there can be border cases, similar to how one can roll a die 10 times and get 10 sixes. It’s unlikely, but not unrealistic, and certain services need that certainty. In the following sections, we dissect this approach.</p>
    <div>
      <h2>First dive into probabilities given a stable request rate</h2>
      <a href="#first-dive-into-probabilities-given-a-stable-request-rate">
        
      </a>
    </div>
    <p>A first approach is to reduce the number of requests going to the origin server. Instead of always sending a request to revalidate, we are going to send 1 out of 10. This means that instead of sending 10 requests per second when the cache is invalidated, we send 1 per second.</p><p>Because we don't have a lock, we do that with probabilities. We set the probability of sending a request to the origin to be $p=\frac{1}{10}$. With a rate $r$ of 10 requests per second, after 1 second, the expectancy of a request being sent to the origin is $1-(1-p)^{10}=65\%$. We draw the evolution of the function $E(r, t)=1-(1-p)^{r \times t}$ representing the expectancy of a request being sent to the server over time.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/78UvqHlQ6Se6cifbla3ozw/111decceed55ba1387b78a75e28f04cc/BLOG-2639_6.jpg" />
          </figure><p><i>Figure 5: Revalidation time $E(t)$ with $r=10$ and $p=\frac{1}{10}$. At time $t$, $E(t)$ is the probability that an early revalidation occurred.</i></p><p>The graph moves very quickly towards $1$. This means we might still have space to reduce the number of requests going to our origin server. We can set a lower probability, such as $p_2=\frac{1}{500}$ (1 request every 5 seconds on average). The graph looks as follows:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/TtLqU9nyKqtYxIz5oJefX/fba679de0599854ba344f19bd0b97939/BLOG-2639_7.jpg" />
          </figure><p><i>Figure 6: Revalidation time $E(t)$ with $r=10$ and $p=\frac{1}{500}$.</i></p><p>This looks great. Let's implement it.</p>
            <pre><code>const CACHE_REVALIDATION_INTERVAL_IN_S = 300
const CACHE_REVALIDATION_PROBABILITY = 1/500

function shouldRevalidate(expirationDate) {
  let remainingCacheTimeInS = (expirationDate.getTime() - Date.now()) / 1000

  if (remainingCacheTimeInS &gt; CACHE_REVALIDATION_INTERVAL_IN_S) {
	return false
  }
  if (remainingCacheTimeInS &lt;= 0) {
	return true
  }
  return Math.random() &lt; CACHE_REVALIDATION_PROBABILITY
}
</code></pre>
            <p><i>Codeblock 5: Image server with early-revalidation and a probabilistic cache using uniform distribution</i></p><p>That's it. If the cache is not close to expiration, we don't revalidate. If the cache is expired, we revalidate. Otherwise, we revalidate based on a probability.</p>
    <div>
      <h2>Adaptive cache revalidation</h2>
      <a href="#adaptive-cache-revalidation">
        
      </a>
    </div>
    <p>Until now, we assumed the picture of the cat received a stable request rate. However, for a real service, this does not necessarily hold. For instance, if instead of 10 requests per second, imagine the service receives only 1. The expectancy function does not look as good. After 5 minutes (300s), $E(r=1, t=300)=45\%$. On the other hand, if the image service is receiving 10,000 requests per second, $E(r=10000, t = 300) \approx 100\%$, but our server receives on average $10000 \times \frac{1}{500} = 20$ requests per second. It would be ideal to design a probability function that would adapt to the request rate.</p><p>That function would return a low probability when expiration time is far in the future, and increase over time such that the cache is revalidated before it expires. It would cap the request rate going to the origin server.</p><p>Let’s design the variation of probability $p$ over 5 minutes. When far from the expiration, the probability to revalidate should be low. This should help match the high request rate. For example, with a request rate of 10k requests per second, we would like the revalidation probability $p$ to be $\frac{1}{100000}$. This ensures the request rates seen by our server are going to be low on average, at about 1 request every 10 seconds. As time passes, we increase this probability to allow for revalidation even at a lower request rate.</p><table><tr><td><p><b>Time to expiration $t$ (in s)</b></p></td><td><p><b>Revalidation probability $p$</b></p></td><td><p><b>Target request rate $r$ (in rps)</b></p></td></tr><tr><td><p>300</p></td><td><p>1/100000</p></td><td><p>10000</p></td></tr><tr><td><p>240</p></td><td><p>1/10000</p></td><td><p>1000</p></td></tr><tr><td><p>180</p></td><td><p>1/1000</p></td><td><p>100</p></td></tr><tr><td><p>120</p></td><td><p>1/100</p></td><td><p>10</p></td></tr><tr><td><p>60</p></td><td><p>1/10</p></td><td><p>1</p></td></tr><tr><td><p>0</p></td><td><p>1</p></td><td><p>-</p></td></tr></table><p><i>Table 1: Variation of revalidation probability over time</i></p><p>For each of these intervals, there is a high likelihood that a request rate <code>$r$</code> will trigger a cache revalidation, and low likelihood that a lower request rate will trigger it. If it does, it's ok.</p><p>We can update our revalidation function as follows:</p>
            <pre><code>const CACHE_REVALIDATION_INTERVAL_IN_S = 300
const CACHE_REVALIDATION_PROBABILITY_PER_MIN = [1/100_000, 1/10_000, 1/1000, 1/100, 1/10, 1]

function shouldRevalidate(expirationDate) {
  let remainingCacheTimeInS = (expirationDate.getTime() - Date.now()) / 1000

  if (remainingCacheTimeInS &gt; CACHE_REVALIDATION_INTERVAL_IN_S) {
	return false
  }
  if (remainingCacheTimeInS &lt;= 0) {
	return true
  }
  let currentMinute = Math.floor(remainingCacheTimeInS/60)
  return Math.random() &lt; CACHE_REVALIDATION_PROBABILITY_PER_MIN[currentMinute]
}
</code></pre>
            <p><i>Codeblock 6: Image server with early-revalidation and a probabilistic cache using piecewise uniform distribution</i></p>
    <div>
      <h2>Optimal cache stampede solution</h2>
      <a href="#optimal-cache-stampede-solution">
        
      </a>
    </div>
    <p>There seems to be a lot of decisions going on here. To solve this, we can reference an academic paper written by A Vattani, T Chierichetti, and K Lowenstein in 2015 called <a href="https://cseweb.ucsd.edu/~avattani/papers/cache_stampede.pdf"><u>Optimal Probabilistic Cache Stampede Prevention</u></a>. If you read it, you'll recognise that what we have been discussing until now is close to what the paper presents. For instance, both the cache revalidation algorithm structure and the early revalidation function look similar.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MLwwNsci3XxhK0uAvWcFu/62a17cc9056d6b12832160acc9e40fb9/BLOG-2639_8.png" />
          </figure><p><i>Figure 7: Probabilistic early expiration of a cache item as defined by Figure 2 of Optimal Probabilistic Cache Stampede Prevention paper. In our case, $\mathcal{D}=300$</i></p><p>One takeaway from the paper is that instead of discretization, with a probability from 0 to 60s, then from 60s to 120s, …, the probability function can be continuous. Instead of a fixed $p$, there is a function $p(t)$ of time $t$.</p><p>$p(t)=e^{-\lambda (expiry-t)}, \text{ with } expiry=300, \text{ and } t \in [0, 300]$</p><p>We call $\lambda$ the steepness parameter, and set it to $\frac{1}{300}$, $300$ being our early expiration gap.</p><p>The expectancy over time is $E(r, t)=1-e^{-rλt}$. This leads to the expectancy below for various request rates. You can note that when $r=1$, there is not a $100%$ chance that the request will be revalidated before expiry.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3lHElc96ZDNbcMfXVQ9pUm/e70e98b4be158dcde11b95366a736742/BLOG-2639_9.jpg" />
          </figure><p><i>Figure 8: Revalidation time $E(t)$ for multiple $r$ with an exponential distribution.</i></p><p>This leads to the final code snippet:</p>
            <pre><code>const CACHE_REVALIDATION_INTERVAL_IN_S = 300
const REVALIDATION_STEEPNESS = 1/300

function shouldRevalidate(expirationDate) {
  let remainingCacheTimeInS = (expirationDate.getTime() - Date.now()) / 1000

  if (remainingCacheTimeInS &gt; CACHE_REVALIDATION_INTERVAL_IN_S) {
	return false
  }
  if (remainingCacheTimeInS &lt;= 0) {
	return true
  }
// p(t) is evaluated here
  return Math.random() &lt; Math.exp(-REVALIDATION_STEEPNESS*remainingCacheTimeInS)
}
</code></pre>
            <p><i>Codeblock 7: Image server with early-revalidation and a probabilistic cache using exponential distribution</i></p><p>And that's it. Given <code>Date.now(</code>) has a granularity, and is not continuous, it would also be possible to discretise these functions, even though the gains are minimal. This is what we have done in a <a href="https://github.com/cloudflare/privacypass-issuer/blob/main/src/cache.ts#L60-L103"><u>production worker implementation</u></a>, where the number of requests is important. It is a service that benefits from caching for performance consideration, and that cannot use built-in <a href="https://developers.cloudflare.com/workers/runtime-apis/cache/"><u>stale-while-revalidate</u></a> from within Cloudflare workers. Probabilistic cache stampede prevention is well-suited here, as no new component has to be built, and it performs well at different request rates.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We have seen how to solve cache stampede without a lock, its implementation, and why it is optimal. In the real world, you likely will not encounter this issue: either because it’s good enough to optimize your origin service to serve more requests, or because you can leverage a CDN cache. In fact, most HTTP caches provide an API that follows <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"><u>Cache Control</u></a>, and likely have all the tools you need. This primitive is also built into certain products, such as <a href="https://developers.cloudflare.com/kv/platform/limits/"><u>Cloudflare KV</u></a>.</p><p>If you have not done so, you can go and experiment with all the code snippets presented in this blog on the Cloudflare Workers Playground at <a href="https://cloudflareworkers.com"><u>cloudflareworkers.com</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">4Xek2BRcXVKNsI4vCa3Zuj</guid>
            <dc:creator>Thibault Meunier</dc:creator>
        </item>
        <item>
            <title><![CDATA[Wrapping up another Birthday Week celebration]]></title>
            <link>https://blog.cloudflare.com/birthday-week-2024-wrap-up/</link>
            <pubDate>Mon, 30 Sep 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ Recapping all the big announcements made during 2024’s Birthday Week. ]]></description>
            <content:encoded><![CDATA[ <p>2024 marks Cloudflare’s 14th birthday. Birthday Week each year is packed with major announcements and the release of innovative new offerings, all focused on giving back to our customers and the broader Internet community. Birthday Week has become a proud tradition at Cloudflare and our culture, to not just stay true to our mission, but to always stay close to our customers. We begin planning for this week of celebration earlier in the year and invite everyone at Cloudflare to participate.</p><p>Months before Birthday Week, we invited teams to submit ideas for what to announce. We were flooded with submissions, from proposals for implementing new standards to creating new products for developers. Our biggest challenge is finding space for it all in just one week — there is still so much to build. Good thing we have a birthday to celebrate each year, but we might need an extra day in Birthday Week next year!</p><p>In case you missed it, here’s everything we announced during 2024’s Birthday Week:</p>
    <div>
      <h3>Monday</h3>
      <a href="#monday">
        
      </a>
    </div>
    <div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span>What</span></span></p>
                    </td>
                    <td>
                        <p><span><span>In a sentence…</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/cloudflare-ai-audit-control-ai-content-crawlers"><span><span><u>Start auditing and controlling the AI models accessing your content</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Understand which AI-related bots and crawlers can access your website, and which content you choose to allow them to consume.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/batched-dns-changes/"><span><span><u>Making zone management more efficient with batch DNS record updates</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Customers using Cloudflare to manage DNS can create a whole batch of records, enable </span></span><a href="https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records/"><span><span>proxying</span></span></a><span><span> on many records, update many records to point to a new target at the same time, or even delete all of their records.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/turnstile-ephemeral-ids-for-fraud-detection"><span><span><u>Introducing Ephemeral IDs: a new tool for fraud detection</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Taking the next step in advancing security with Ephemeral IDs, a new feature that generates a unique short-lived ID, without relying on any network-level information.</span></span></p>
                        <p> </p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Tuesday</h3>
      <a href="#tuesday">
        
      </a>
    </div>
    <div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span>What</span></span></p>
                    </td>
                    <td>
                        <p><span><span>In a sentence…</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/safer-resolver/"><span><span><u>Cloudflare partners to deliver safer browsing experience to homes</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Internet service, network, and hardware equipment providers can </span></span><a href="https://docs.google.com/spreadsheets/d/1ZIBbVz2gqPBsldhszk_Wo2eZeNwAZ5Mf9xSssxRrTuc/edit?resourcekey=&amp;gid=386353769#gid=386353769"><span><span><u>sign up</u></span></span></a><span><span> and partner with Cloudflare to deliver a safer browsing experience to homes.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/a-safer-internet-with-cloudflare/"><span><span><u>A safer Internet with Cloudflare: free threat intelligence, analytics, and new threat detections</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Free threat intelligence, analytics, new threat detections, and more.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/automatically-generating-cloudflares-terraform-provider/"><span><span><u>Automatically generating Cloudflare’s Terraform provider</u></span></span></a></p>
                        <p> </p>
                    </td>
                    <td>
                        <p><span><span>The last pieces of the OpenAPI schemas ecosystem to now be automatically generated — the Terraform provider and API reference documentation.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/key-transparency/"><span><span><u>Cloudflare helps verify the security of end-to-end encrypted messages by auditing key transparency for WhatsApp</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Cloudflare helps verify the security of end-to-end encrypted messages by auditing key transparency for WhatsApp.</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Wednesday</h3>
      <a href="#wednesday">
        
      </a>
    </div>
    <div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span>What</span></span></p>
                    </td>
                    <td>
                        <p><span><span>In a sentence…</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/introducing-speed-brain/"><span><span><u>Introducing Speed Brain: helping web pages load 45% faster</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Speed Brain, our latest leap forward in speed, uses the Speculation Rules API to prefetch content for users' likely next navigations — downloading web pages before they navigate to them and making pages load 45% faster.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/instant-purge/"><span><span><u>Instant Purge: invalidating cached content in under 150ms</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Instant Purge invalidates cached content in under 150ms, offering the industry's fastest cache purge with global latency for purges by tags, hostnames, and prefixes.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/new-standards/"><span><span><u>New standards for a faster and more private Internet</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Zstandard compression, Encrypted Client Hello, and more speed and privacy announcements all released for free.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/webrtc-turn-using-anycast/"><span><span><u>TURN and anycast: making peer connections work globally</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Starting today, </span></span><a href="https://developers.cloudflare.com/calls/turn/"><span><span>Cloudflare Calls’ TURN service</span></span></a><span><span> is now generally available to all Cloudflare accounts.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/gen-12-servers"><span><span><u>Cloudflare’s 12th Generation servers — 145% more performant and 63% more efficient</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Next generation servers focused on exceptional performance and security, enhanced support for AI/ML workloads, and significant strides in power efficiency.</span></span></p>
                        <p> </p>
                        <p><span><span> </span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Thursday</h3>
      <a href="#thursday">
        
      </a>
    </div>
    <div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span>What</span></span></p>
                    </td>
                    <td>
                        <p><span><span>In a sentence…</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/startup-program-250k-credits"><span><span><u>Startup Program revamped: build and grow on Cloudflare with up to $250,000 in credits</u></span></span></a></p>
                        <p> </p>
                    </td>
                    <td>
                        <p><span><span>Eligible startups can now apply to receive up to $250,000 in credits to build using Cloudflare's Developer Platform.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/workers-ai-bigger-better-faster"><span><span><u>Cloudflare’s bigger, better, faster AI platform </u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>More powerful GPUs, expanded model support, enhanced logging and evaluations in AI Gateway, and Vectorize GA with larger index sizes and faster queries.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/builder-day-2024-announcements"><span><span><u>Builder Day 2024: 18 big updates to the Workers platform</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Persistent and queryable Workers logs, Node.js compatibility GA, improved Next.js support via OpenNext, built-in CI/CD for Workers, Gradual Deployments, Queues, and R2 Event Notifications GA, and more — making building on Cloudflare easier, faster, and more affordable.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/faster-workers-kv"><span><span><u>Faster Workers KV</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>A deep dive into how we made Workers KV up to 3x faster.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/sqlite-in-durable-objects"><span><span><u>Zero-latency SQLite storage in every Durable Object</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Putting your application code into the storage layer, so your code runs where the data is stored.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/making-workers-ai-faster/"><span><span><u>Making Workers AI faster and more efficient: Performance optimization with KV cache compression and speculative decoding</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Using new optimization techniques such as KV cache compression and speculative decoding, we’ve made large language model (LLM) inference lightning-fast on the Cloudflare Workers AI platform.</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Friday</h3>
      <a href="#friday">
        
      </a>
    </div>
    <div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span>What</span></span></p>
                    </td>
                    <td>
                        <p><span><span>In a sentence…</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/container-platform-preview"><span><span><u>Our container platform is in production. It has GPUs. Here’s an early look.</u></span></span></a></p>
                        <p> </p>
                    </td>
                    <td>
                        <p><span><span>We’ve been working on something new — a platform for running containers across Cloudflare’s network. We already use it in production, for AI inference and more.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/cisa-pledge-commitment-bug-bounty-vip"><span><span><u>Advancing cybersecurity: Cloudflare implements a new bug bounty VIP program as part of CISA Pledge commitment</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>We implemented a new bug bounty VIP program this year as part of our CISA Pledge commitment.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/launchpad-cohort4-dev-starter-pack/"><span><span><u>Empowering builders: introducing the Dev Alliance and Workers Launchpad Cohort #4</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Get free and discounted access to essential developer tools and meet the latest set of incredible startups building on Cloudflare.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/expanding-our-support-for-oss-projects-with-project-alexandria"><span><span><u>Expanding our support for open source projects with Project Alexandria</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Expanding our open source program and helping projects have a sustainable and scalable future, providing tools and protection needed to thrive.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/radar-data-explorer-ai-assistant"><span><span><u>Network trends and natural language: Cloudflare Radar’s new Data Explorer &amp; AI Assistant</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>A simple Web-based interface to build more complex API queries, including comparisons and filters, and visualize the results.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/bringing-ai-to-cloudflare"><span><span><u>AI Everywhere with the WAF Rule Builder Assistant, Cloudflare Radar AI Insights, and updated AI bot protection</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Extending our AI Assistant capabilities to help you build new WAF rules, added new AI bot and crawler traffic insights to Radar, and new AI bot blocking capabilities.</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><a href="https://blog.cloudflare.com/cloudflares-commitment-to-free"><span><span><u>Reaffirming our commitment to Free</u></span></span></a></p>
                    </td>
                    <td>
                        <p><span><span>Our free plan is here to stay, and we reaffirm that commitment this week with 15 releases that make the Free plan even better.</span></span></p>
                        <p> </p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h2>One more thing…</h2>
      <a href="#one-more-thing">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5FReOqd5AHo8vTgSmY6qe6/1ae02d93ec9d9af2f60c0b6024017f58/image3.png" />
          </figure><p>Cloudflare serves millions of customers and their millions of domains across nearly every country on Earth. However, as a global company, the payment landscape can be complex — especially in regions outside of North America. While credit cards are very popular for online purchases in the US, the global picture is quite different. <a href="https://www.fisglobal.com/-/media/fisglobal/files/campaigns/global-payments%20report/FIS_TheGlobalPaymentsReport_2023.pdf"><u>60% of consumers across EMEA, APAC and LATAM choose alternative payment methods</u></a>. For instance, European consumers often opt for SEPA Direct Debit, a bank transfer mechanism, while Chinese consumers frequently use Alipay, a digital wallet.</p><p>At Cloudflare, we saw this as an opportunity to meet customers where they are. Today, we're thrilled to announce that we are expanding our payment system and launching a closed beta for a new payment method called <a href="https://www.cloudflare.com/lp/cloudflare-introduces-stripe-link/"><u>Stripe Link</u></a>. The checkout experience will be faster and more seamless, allowing our self-serve customers to pay using saved bank accounts or cards with Link. Customers who have saved their payment details at any business using Link can quickly check out without having to reenter their payment information.</p><p>These are the first steps in our efforts to expand our payment system to support global payment methods used by customers around the world.<b> </b>We'll be rolling out new payment methods gradually, ensuring a smooth integration and gathering feedback from our customers every step of the way.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/v0v7QBRWeGSfArq6jE5eg/7d8d79cbfe3f63386db52469c4727d21/image2.png" />
          </figure>
    <div>
      <h2>Until next year</h2>
      <a href="#until-next-year">
        
      </a>
    </div>
    <p>That’s all for Birthday Week 2024. However, the innovation never stops at Cloudflare. Continue to follow the <a href="https://blog.cloudflare.com/"><u>Cloudflare Blog</u></a> all year long as we launch more products and features that help build a better Internet.</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Workers Launchpad]]></category>
            <category><![CDATA[Workers AI]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Turnstile]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed]]></category>
            <category><![CDATA[Speed Brain]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[AI]]></category>
            <guid isPermaLink="false">65JnLP0MYKVzwTyOsItRJk</guid>
            <dc:creator>Kelly May Johnston</dc:creator>
            <dc:creator>Brendan Irvine-Broque</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Speed Brain: helping web pages load 45% faster]]></title>
            <link>https://blog.cloudflare.com/introducing-speed-brain/</link>
            <pubDate>Wed, 25 Sep 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ Speed Brain uses the Speculation Rules API to prefetch content for the user's likely next navigations. The goal is to download a web page to the browser before a user navigates to it. 
 ]]></description>
            <content:encoded><![CDATA[ <p>Each time a user visits your web page, they are initiating a race to receive content as quickly as possible. Performance is a critical <a href="https://www.speedcurve.com/blog/psychology-site-speed/"><u>factor</u></a> that influences how visitors interact with your site. Some might think that moving content across the globe introduces significant latency, but for a while, network transmission speeds have approached their <a href="https://blog.cloudflare.com/fastest-internet/"><u>theoretical limits</u></a>. To put this into perspective, data on Cloudflare can traverse the 11,000 kilometer round trip between New York and London in about 76 milliseconds – faster than the <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4043155/#:~:text=one%20blink%20lasts%20about%201/3%20s"><u>blink of an eye</u></a>.</p><p>However, delays in loading web pages persist due to the complexities of processing requests, responses, and configurations. In addition to pushing advancements in <a href="https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/"><u>connection establishment</u></a>, <a href="https://blog.cloudflare.com/this-is-brotli-from-origin/"><u>compression</u></a>, <a href="https://blog.cloudflare.com/cloudflare-gen-12-server-bigger-better-cooler-in-a-2u1n-form-factor/"><u>hardware</u></a>, and <a href="https://blog.cloudflare.com/pingora-open-source/"><u>software</u></a>, we have built a new way to reduce page load latency by anticipating how visitors will interact with a given web page. </p><p>Today we are very excited to share the latest leap forward in speed: <b>Speed Brain</b>. It relies on the <a href="https://developer.chrome.com/docs/web-platform/prerender-pages"><u>Speculation Rules API </u></a>to <a href="https://developer.mozilla.org/en-US/docs/Glossary/Prefetch"><u>prefetch</u></a> the content of the user's likely next navigations. The main goal of Speed Brain is to download a web page to the browser cache before a user navigates to it, allowing pages to load almost instantly when the actual navigation takes place. </p><p>Our initial approach uses a <a href="https://developer.chrome.com/blog/speculation-rules-improvements#eagerness"><u>conservative</u></a> model that prefetches static content for the next page when a user starts a touch or <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event"><u>click event</u></a>. Through the fourth quarter of 2024 and into 2025, we will offer more aggressive speculation models, such as speculatively <a href="https://developer.mozilla.org/en-US/docs/Glossary/Prerender"><u>prerendering</u></a> (not just fetching the page before the navigation happens but rendering it completely) for an even faster experience. Eventually, Speed Brain will learn how to eliminate latency for your static website, without any configuration, and work with browsers to make sure that it loads as fast as possible.  </p><p>To illustrate, imagine an ecommerce website selling clothing. Using the insights from our global request logs, we can predict with high accuracy that a typical visitor is likely to click on ‘Shirts’ when viewing the parent page ‘Mens &gt; Clothes’. Based on this, we can start delivering static content, like images, before the shopper even clicks the ‘Shirts’ link. As a result, when they inevitably click, the page loads instantly. <b>Recent lab testing of our aggressive loading model implementation has shown up to a 75% reduction in </b><a href="https://developer.mozilla.org/en-US/docs/Glossary/Largest_contentful_paint"><b><u>Largest Contentful Paint (LCP)</u></b></a>, the time it takes for the largest visible element (like an image, video, or text block) to load and render in the browser.</p><p>The best part? We are making Speed Brain available to all plan types immediately and at no cost. Simply toggle on the Speed Brain feature for your website from the <a href="https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization/content"><u>dashboard</u></a> or the <a href="https://developers.cloudflare.com/api/operations/zone-settings-get-speed-brain-setting"><u>API</u></a>. It’ll feel like magic, but behind the scenes it's a lot of clever engineering. </p><p>We have already enabled Speed Brain by default on <u>all</u> free domains and are seeing a <b>reduction in LCP of 45% on successful prefetches.</b> Pro, Business, and Enterprise domains need to enable Speed Brain manually. If you have not done so already, we <b>strongly</b> recommend also <a href="https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare"><u>enabling Real User Measurements (RUM)</u></a> via your dashboard so you can see your new and improved web page performance. As a bonus, enabling RUM for your domain will help us provide <b>improved</b> and <b>customized</b> prefetching and prerendering rules for your website in the near future!</p>
    <div>
      <h2>How browsers work at a glance</h2>
      <a href="#how-browsers-work-at-a-glance">
        
      </a>
    </div>
    <p>Before discussing how Speed Brain can help load content exceptionally fast, we need to take a step back to review the complexity of loading content on browsers. Every time a user navigates to your web page, a series of request and response cycles must be completed. </p><p>After the browser <a href="https://www.debugbear.com/blog/http-server-connections"><u>establishes a secure connection</u></a> with a server, it sends an HTTP request to retrieve the base document of the web page. The server processes the request, constructs the necessary HTML document and sends it back to the browser in the response. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6hxlOWcShKyU4y6sqNYQs1/5717e4ebc130887376d629f9926d7a98/BLOG-2422_2.png" />
          </figure><p>When the browser receives an HTML document, it immediately begins <a href="https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work#parsing"><u>parsing</u></a> the content. During this process, it may encounter references to external resources such as CSS files, JavaScript, images, and fonts. These subresources are essential for rendering the page correctly, so the browser issues additional HTTP requests to fetch them. However, if these resources are available in the browser’s cache, the browser can retrieve them locally, significantly reducing <a href="https://www.cloudflare.com/learning/performance/glossary/what-is-latency/"><u>network latency</u></a> and improving page load times.</p><p>As the browser processes HTML, CSS, and JavaScript, the rendering engine begins to display content on the screen. Once the page’s visual elements are displayed, user interactions — like clicking a link — prompt the browser to restart much of this process to fetch new content for the next page. This workflow is typical of every browsing session: as users navigate, the browser continually fetches and renders new or uncached resources, introducing a delay before the new page fully loads.</p><p>Take the example of a user navigating the shopping site described above. As the shopper moves from the homepage to the ‘men's’ section of the site to the ‘clothing’ section to the ‘shirts’ section, the time spent on retrieving each of those subsequent pages can add up and contribute to the shopper leaving the site before they complete the transaction.  </p><p>Ideally, having prefetched and prerendered pages present in the browser at the time each of those links are clicked would eliminate much of the network latency impact, allowing the browser to load content instantly and providing a smoother user experience. </p>
    <div>
      <h2>Wait, I’ve heard this story before (how did we get to Speed Brain?)</h2>
      <a href="#wait-ive-heard-this-story-before-how-did-we-get-to-speed-brain">
        
      </a>
    </div>
    <p>We know what you’re thinking. We’ve had prefetching for years. There have even been several speculative prefetching efforts in the past. You’ve heard this all before. How is this different now?</p><p>You’re right, of course. Over the years, there has been a constant effort by developers and browser vendors to optimize page load times and enhance user experience across the web. Numerous techniques have been developed, spanning various layers of the Internet stack — from optimizing network layer connectivity to preloading application content closer to the client.</p>
    <div>
      <h4>Early prefetching: lack of data and flexibility</h4>
      <a href="#early-prefetching-lack-of-data-and-flexibility">
        
      </a>
    </div>
    <p>Web prefetching has been one such technique that has existed for more than a decade. It is based on the assumption that certain subresources are likely to be needed in the near future, so why not fetch them proactively? This could include anything from HTML pages to images, stylesheets, or scripts that the user might need as they navigate through a website. In fact, the core concept of speculative execution is not new, as it's a general technique that's been employed in various areas of computer science for years, with <a href="https://en.wikipedia.org/wiki/Branch_predictor"><u>branch prediction</u></a> in CPUs as a prime example.</p><p>In the early days of the web, several custom prefetching solutions emerged to enhance performance. For example, in 2005, Google introduced the <a href="https://google.fandom.com/wiki/Google_Web_Accelerator"><u>Google Web Accelerator</u></a>, a client-side application aimed at speeding up browsing for broadband users. Though innovative, the project was short-lived due to privacy and compatibility issues (we will describe how Speed Brain is different below). Predictive prefetching at that time lacked the data insights and API support for capturing user behavior, especially those handling sensitive actions like deletions or purchases.</p>
    <div>
      <h4>Static lists and manual effort</h4>
      <a href="#static-lists-and-manual-effort">
        
      </a>
    </div>
    <p>Traditionally, prefetching has been accomplished through the use of the <code>&lt;link rel="prefetch"&gt;</code> attribute as one of the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/prefetch"><u>Resource Hints</u></a>. Developers had to manually specify the attribute on each page for each resource they wanted the browser to preemptively fetch and cache in memory. This manual effort has not only been laborious but developers often lacked insight into what resources should be prefetched, which reduced the quality of their specified hints.</p><p>In a similar vein, <a href="https://developers.cloudflare.com/speed/optimization/content/prefetch-urls/"><u>Cloudflare has offered a URL prefetching feature since 2015</u></a>. Instead of prefetching in browser cache, Cloudflare allows customers to prefetch a static list of resources into the CDN cache. The feature allows prefetching resources in advance of when they are actually needed, usually during idle time or when network conditions are favorable. However, similar concerns apply for CDN prefetching, since customers have to manually decide on what resources are good candidates for prefetching for each page they own. If misconfigured, static link prefetching can be a <a href="https://en.wiktionary.org/wiki/footgun"><u>footgun</u></a>, causing the web page load time to actually slow down.</p>
    <div>
      <h4>Server Push and its struggles</h4>
      <a href="#server-push-and-its-struggles">
        
      </a>
    </div>
    <p><a href="https://datatracker.ietf.org/doc/html/rfc9113#name-server-push"><u>HTTP/2’s "server push"</u></a> was another attempt to improve web performance by pushing resources to the client before they were requested. In theory, this would reduce latency by eliminating the need for additional round trips for future assets. However, the server-centric dictatorial nature of "pushing" resources to the client raised significant challenges, primarily due to lack of context about what was already cached in the browser. This not only wasted bandwidth but had the potential to slow down the delivery of critical resources, like base HTML and CSS, due to race conditions on browser fetches when rendering the page. The <a href="https://datatracker.ietf.org/doc/html/draft-kazuho-h2-cache-digest-01"><u>proposed solution of cache digests</u></a>, which would have informed servers about client cache contents, never gained widespread implementation, leaving servers to push resources blindly. <a href="https://developer.chrome.com/blog/removing-push"><u>In October 2022, Google Chrome removed Server Push support</u></a>, and in September 2024, <a href="https://groups.google.com/a/mozilla.org/g/dev-platform/c/vU9hJg343U8/m/4cZsHz7TAQAJ"><u>Firefox followed suit</u></a>.</p>
    <div>
      <h4>A step forward with Early Hints</h4>
      <a href="#a-step-forward-with-early-hints">
        
      </a>
    </div>
    <p>As a successor, <a href="https://datatracker.ietf.org/doc/html/rfc8297"><u>Early Hints</u></a> was specified in 2017 but not widely adopted until 2022, when <a href="https://blog.cloudflare.com/early-hints"><u>we partnered with browsers and key customers to deploy it</u></a>. It offers a more efficient alternative by "hinting" to clients which resources to load, allowing better prioritization based on what the browser needs. Specifically, the server sends a 103 Early Hints HTTP status code with a list of key page assets that the browser should start loading while the main response is still being prepared. This gives the browser a head start in fetching essential resources and avoids redundant preloading if assets are already cached. Although Early Hints doesn't adapt to user behaviors or dynamic page conditions (yet), its use is primarily limited to preloading specific assets rather than full web pages — in particular, cases where there is a long server “think time” to produce HTML.</p><p>As the web evolves, tools that can handle complex, dynamic user interactions will become increasingly important to balance the performance gains of speculative execution with its potential drawbacks for end-users. For years Cloudflare has offered performance-based solutions that adapt to user behavior and work to balance the speed and correctness decisions across the Internet like <a href="https://www.cloudflare.com/application-services/products/argo-smart-routing/"><u>Argo Smart Routing</u></a>, <a href="https://blog.cloudflare.com/introducing-smarter-tiered-cache-topology-generation/"><u>Smart Tiered Cache</u></a>, and <a href="https://developers.cloudflare.com/workers/configuration/smart-placement/"><u>Smart Placement</u></a>. Today we take another step forward toward an adaptable framework for serving content lightning-fast. </p>
    <div>
      <h2>Enter Speed Brain: what makes it different?</h2>
      <a href="#enter-speed-brain-what-makes-it-different">
        
      </a>
    </div>
    <p>Speed Brain offers a robust approach for implementing predictive prefetching strategies directly within the browser based on the ruleset returned by our servers. By building on lessons from previous attempts, it shifts the responsibility for resource prediction to the client, enabling more dynamic and personalized optimizations based on user interaction – like hovering over a link, for example – and their device capabilities. Instead of the browser sitting idly waiting for the next web page to be requested by the user, it takes cues from how a user is interacting with a page and begins asking for the next web page before the user finishes clicking on a link.</p><p>Behind the scenes, all of this magic is made possible by the <a href="https://developer.chrome.com/docs/web-platform/prerender-pages#speculation-rules-api"><u>Speculation Rules API</u></a>, which is an emerging standard in the web performance space from Google. When Cloudflare’s Speed Brain feature is enabled, an HTTP header called Speculation-Rules is added to web page responses. The value for this header is a URL that hosts an opinionated Rules configuration. This configuration instructs the browser to initiate prefetch requests for future navigations. Speed Brain does not improve page load time for the first page that is visited on a website, but it can improve it for subsequent web pages that are visited on the same site.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Fu2ADDum0Pp9e5kq94Jd4/3eba0ffc4d94c42af67d4e9c1c708a29/BLOG-2422_3.png" />
          </figure><p>The idea seems simple enough, but <a href="https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API#unsafe_prefetching"><u>prefetching comes with challenges</u></a>, as some prefetched content may never end up being used. With the initial release of Speed Brain, we have designed a solution with guardrails that addresses two important but distinct issues that limited previous speculation efforts — <i>stale prefetch configuration</i> and <i>incorrect prefetching. </i>The Speculation Rules API configuration we have chosen for this initial release has been carefully designed to balance safety of prefetching while still maintaining broad applicability of rules for the entire site.</p>
    <div>
      <h4>Stale prefetch configuration</h4>
      <a href="#stale-prefetch-configuration">
        
      </a>
    </div>
    <p>As websites inevitably change over time, static prefetch configurations often become outdated, leading to <a href="https://www.cloudflare.com/learning/cdn/common-cdn-issues/">inefficient or ineffective prefetching</a>. This has been especially true for techniques like the rel=prefetch attribute or static CDN prefetching URL sets, which have required developers to manually maintain relevant prefetchable URL lists for each page of their website. Most static prefetch lists are based on developer intuition rather than real user navigation data, potentially missing important prefetch opportunities or wasting resources on unnecessary prefetches. </p>
    <div>
      <h4>Incorrect prefetching</h4>
      <a href="#incorrect-prefetching">
        
      </a>
    </div>
    <p>Since prefetch requests are just like normal requests except with a `sec-purpose` HTTP request header, they incur the same overhead on the client, network, and server. However, the crucial difference is that prefetch requests anticipate user behavior and the response might not end up being used, <a href="https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API#unsafe_prefetching"><u>so all that overhead might be wasted</u></a>. This makes prefetch accuracy extremely important — that is, maximizing the percentage of prefetched pages that end up being viewed by the user. Incorrect prefetching can lead to inefficiencies and unneeded costs, such as caching resources that aren't requested, or wasting bandwidth and network resources, which is especially critical on metered mobile networks or in low-bandwidth environments.</p>
    <div>
      <h3>Guardrails</h3>
      <a href="#guardrails">
        
      </a>
    </div>
    <p>With the initial release of Speed Brain, we have designed a solution with important side effect prevention guardrails that completely removes the chance of <i>stale prefetch configuration</i>, and minimizes the risk of<i> incorrect prefetching</i>. This opinionated configuration is achieved by leveraging the <a href="https://developer.chrome.com/blog/speculation-rules-improvements"><u>document rules</u></a> and <a href="https://developer.chrome.com/blog/speculation-rules-improvements#eagerness"><u>eagerness</u></a> settings from the <a href="https://developer.chrome.com/docs/web-platform/prerender-pages#speculation-rules-api"><u>Speculation Rules API</u></a>. Our chosen configuration looks like the following:</p>
            <pre><code>{
  "prefetch": [{
    "source": "document",
    "where": {
      "and": [
        { "href_matches": "/*", "relative_to": "document" },
      ]
    },
    "eagerness": "conservative"
  }]
}
</code></pre>
            
    <div>
      <h5>
Document Rules</h5>
      <a href="#document-rules">
        
      </a>
    </div>
    <p><a href="https://developer.chrome.com/blog/speculation-rules-improvements"><u>Document Rules</u></a>, indicated by "source": "document" and the "where" key in the configuration, allows prefetching to be applied dynamically over the entire web page. This eliminates the need for a predefined static URL list for prefetching. Hence, we remove the problem of <i>stale prefetch configuration</i> as prefetch candidate links are determined based on the active page structure.</p><p>Our use of "relative_to": "document" in the where clause instructs the browser to limit prefetching to same-site links. This has the added bonus of allowing our implementation to avoid cross-origin prefetches to avoid any privacy implications for users, as it doesn’t follow them around the web. </p>
    <div>
      <h5>Eagerness</h5>
      <a href="#eagerness">
        
      </a>
    </div>
    <p><a href="https://developer.chrome.com/docs/web-platform/prerender-pages#eagerness"><u>Eagerness</u></a> controls how aggressively the browser prefetches content. There are four possible settings:</p><ul><li><p><b><i>immediate</i></b><i>: Used as soon as possible on page load — generally as soon as the rule value is seen by the browser, it starts prefetching the next page.</i></p></li><li><p><b><i>eager</i></b><i>: Identical to immediate setting above, but the prefetch trigger additionally relies on slight user interaction events, such as moving the cursor towards the link (coming soon).</i></p></li><li><p><b><i>moderate</i></b><i>: Prefetches if you hold the pointer over a link for more than 200 milliseconds (or on the </i><a href="https://developer.mozilla.org/docs/Web/API/Element/pointerdown_event"><i><u>pointerdown</u></i></a><i> event if that is sooner, and on mobile where there is no hover event).</i></p></li><li><p><b><i>conservative</i></b><i>: Prefetches on pointer or touch down on the link.</i></p></li></ul><p>Our initial release of Speed Brain makes use of the <b><u>conservative</u></b> eagerness value to minimize the risk of incorrect prefetching, which can lead to unintended resource waste while making your websites noticeably faster. While we lose out on the potential performance improvements that the more aggressive eagerness settings offer, we chose this cautious approach to prioritize safety for our users. Looking ahead, we plan to explore more dynamic eagerness settings for sites that could benefit from a more liberal setting, and we'll also expand our rules to include <a href="https://developer.mozilla.org/en-US/docs/Glossary/Prerender"><u>prerendering</u></a>.</p><p>Another important safeguard we implement is to only accept prefetch requests for static content that is already stored in our CDN cache. If the content isn't in the cache, we reject the prefetch request. Retrieving content directly from our CDN cache for prefetching requests lets us bypass concerns about their cache eligibility. The rationale for this is straightforward: if a page is not eligible for caching, we don't want it to be prefetched in the browser cache, as it could lead to unintended consequences and increased origin load. For instance, prefetching a logout page might log the user out prematurely before the user actually finishes their action. Stateful prefetching or prerendering requests can have unpredictable effects, potentially altering the server's state for actions the client has not confirmed. By only allowing prefetching for pages already in our CDN cache, we have confidence those pages will not negatively impact the user experience.</p><p>These guardrails were implemented to work in performance-sensitive environments. We measured the impact of our baseline conservative deployment model on all pages across <a href="https://developers.cloudflare.com/"><u>Cloudflare’s developer documentation</u></a> in early July 2024. We found that we were able to prefetch the correct content, content that would in fact be navigated to by the users, <b>94</b>% of the time. We did this while improving the performance of the navigation by reducing LCP at p75 quantile by <b>40</b>% without inducing any unintended side effects. The results were amazing!</p>
    <div>
      <h2>Explaining Cloudflare’s implementation </h2>
      <a href="#explaining-cloudflares-implementation">
        
      </a>
    </div>
    <p>Our global <a href="https://www.cloudflare.com/network"><u>network</u></a> spans over 330 cities and operates within 50 milliseconds of 95% of the Internet-connected population. This extensive reach allows us to significantly improve the performance of cacheable assets for our customers. By leveraging this network for smart prefetching with Speed Brain, Cloudflare can serve prefetched content directly from the CDN cache, reducing network latency to practically instant.</p><p>Our unique position on the network provides us the leverage to automatically enable Speed Brain without requiring any changes from our customers to their origin server configurations. It's as simple as flipping a switch! Our first version of Speed Brain is now live.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/O3RwzUlOj1GlJuMSrq5TW/55d9ef31a2de21034eb036b8c029d5b6/BLOG-2422_4.png" />
          </figure><ul><li><p>Upon receiving a request for a web page with Speed Brain enabled, the Cloudflare server returns an additional "Speculation-Rules" HTTP response header. The value for this header is a URL that hosts an opinionated Rules configuration (as mentioned above).</p></li><li><p>When the browser begins parsing the response header, it fetches our Speculation-Rules configuration, and loads it as part of the web page.</p></li><li><p>The configuration guides the browser on when to prefetch the next likely page from Cloudflare that the visitor may navigate to, based on how the visitor is engaging with the page.</p></li><li><p>When a user action (such as mouse down event on the next page link) triggers the Rules application, the browser sends a prefetch request for that page with the "sec-purpose: prefetch" HTTP request header.</p></li><li><p>Our server parses the request header to identify the prefetch request. If the requested content is present in our cache, we return it; otherwise,<b> we return a 503 HTTP status </b>code and deny the prefetch request. This removes the risk of unsafe side-effects of sending requests to origins or Cloudflare Workers that are unaware of prefetching. Only content present exclusively in the cache is returned.</p></li><li><p>On a success response, the browser successfully prefetches the content in memory, and when the visitor navigates to that page, the browser directly loads the web page from the browser cache for immediate rendering.</p></li></ul>
    <div>
      <h2>Common troubleshooting patterns </h2>
      <a href="#common-troubleshooting-patterns">
        
      </a>
    </div>
    <p>Support for Speed Brain relies on the <a href="https://developer.chrome.com/docs/web-platform/prerender-pages"><u>Speculation Rules API</u></a>, an emerging web standard. As of September 2024, <a href="https://caniuse.com/mdn-http_headers_speculation-rules"><u>support for this emerging standard</u></a> is limited to <b>Chromium-based browsers (version 121 or later)</b>, such as Google Chrome and Microsoft Edge. As the web community reaches consensus on API standardization, we hope to see wider adoption across other browser vendors.</p><p>Prefetching by nature does not apply to dynamic content, as the state of such content can change, potentially leading to stale or outdated data being delivered to the end user as well as increased origin load. Therefore, Speed Brain will only work for non-dynamic pages of your website that are cached on our network. It has no impact on the loading of dynamic pages. To get the most benefit out of Speed Brain, we suggest making use of <a href="https://developers.cloudflare.com/cache/how-to/cache-rules/"><u>cache rules</u></a> to ensure that all static content (<b>especially HTML content</b>) on your site is eligible for caching.</p><p>When the browser receives a 503 HTTP status code in response to a speculative prefetch request (marked by the sec-purpose: prefetch header), it cancels the prefetch attempt. Although a 503 error appearing in the browser's console may seem alarming, it is completely harmless for prefetch request cancellation. In our early tests, the 503 response code has caused some site owners concern. We are working with our partners to iterate on this to improve the client experience, but for now follow the specification guidance, <a href="https://developer.mozilla.org/en-US/docs/Web/API/Speculation_Rules_API#:~:text=Using%20a%20non%2Dsuccess%20code%20(for%20example%20a%20503)%20is%20the%20easiest%20way%20to%20prevent%20speculative%20loading"><u>which suggests a 503 response</u></a> for the browser to safely discard the speculative request. We're in active discussions with Chrome, based on feedback from early beta testers, and believe a new non-error dedicated response code would be more appropriate, and cause less confusion. In the meantime, 503 response logs for prefetch requests related to Speed Brain are harmless. If your tooling makes ignoring these requests difficult, you can temporarily disable Speed Brain until we work out something better with the Chrome Team.</p><p>Additionally, when a website uses both its own custom Speculation Rules and Cloudflare's Speed Brain feature, both rule sets can operate simultaneously. Cloudflare’s guardrails will limit speculation rules to cacheable pages, which may be an unexpected limitation for those with existing implementations. If you observe such behavior, consider disabling one of the implementations for your site to ensure consistency in behavior. Note that if your origin server responses include the Speculation-Rules header, it will not be overridden. Therefore, the potential for ruleset conflicts primarily applies to predefined in-line speculation rules.</p>
    <div>
      <h2>How can I see the impact of Speed Brain?</h2>
      <a href="#how-can-i-see-the-impact-of-speed-brain">
        
      </a>
    </div>
    <p>In general, we suggest that you use Speed Brain and most other Cloudflare performance <a href="https://developers.cloudflare.com/speed/"><u>features</u></a> with our <a href="https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare"><u>RUM performance measurement tool</u></a> enabled. Our RUM feature helps developers and website operators understand how their end users are experiencing the performance of their application, providing visibility into:</p><ul><li><p><b>Loading</b>: How long did it take for content to become available?</p></li><li><p><b>Interactivity</b>: How responsive is the website when users interact with it?</p></li><li><p><b>Visual stability</b>: How much does the page move around while loading?</p></li></ul><p>With RUM enabled, you can navigate to the Web Analytics section in the dashboard to see important information about how Speed Brain is helping reduce latency in your <a href="https://www.cloudflare.com/learning/performance/what-are-core-web-vitals/"><u>core web vitals</u></a> metrics like Largest Contentful Paint (LCP) and load time. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6zv2kRvsot12PSNwwaWCad/25e9e56d6f3769b04a8752f99c656f3b/BLOG-2422_5.png" />
          </figure><p><sub><i>Example RUM dashboard for a website with a high amount of prefetchable content that enabled Speed Brain around September 16.</i></sub></p>
    <div>
      <h2>What have we seen in our rollout so far? </h2>
      <a href="#what-have-we-seen-in-our-rollout-so-far">
        
      </a>
    </div>
    <p>We have enabled this feature by default on all free plans and have observed the following:</p>
    <div>
      <h3>Domains</h3>
      <a href="#domains">
        
      </a>
    </div>
    <p>Cloudflare currently has tens of millions of domains using Speed Brain. We have measured the LCP at the 75th quantile (p75) for these sites and found an improvement for these sites between 40% and 50% (average around 45%). </p><p>We found this improvement by comparing navigational prefetches to normal (non-prefetched) page loads for the same set of domains. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/fNrRh84I3iZpHiEieNPg8/a789d9d9a736a8eb76fa6120a84cdf10/BLOG-2422_6.png" />
          </figure>
    <div>
      <h3>Requests</h3>
      <a href="#requests">
        
      </a>
    </div>
    <p>Before Speed Brain is enabled, the p75 of free websites on Cloudflare experience an LCP around 2.2 seconds. With Speed Brain enabled, these sites see significant latency savings on LCP. In aggregate, Speed Brain saves about 0.88 seconds on the low end and up to 1.1 seconds on each successful prefetch! </p>
    <div>
      <h3>Applicable browsers</h3>
      <a href="#applicable-browsers">
        
      </a>
    </div>
    <p>Currently, the Speculation Rules API is only available in Chromium browsers. From Cloudflare Radar, we can see that approximately <a href="https://radar.cloudflare.com/adoption-and-usage"><u>70% of requests</u></a> from visitors are from <a href="https://en.wikipedia.org/wiki/Chromium_(web_browser)"><u>Chromium</u></a> (Chrome, Edge, etc) browsers.</p>
    <div>
      <h3>Across the network</h3>
      <a href="#across-the-network">
        
      </a>
    </div>
    <p>Cloudflare sees hundreds of billions of requests for HTML content each day. Of these requests, about half are cached (make sure your HTML is cacheable!). Around 1% of those requests are for navigational prefetching made by the visitors. This represents significant savings every day for visitors to websites with Speed Brain enabled. Every 24 hours, <b>Speed Brain can save more than 82 years worth of latency!</b></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5CIpcdPC17LY2EGjNxCjNo/cf1a915d16384e32d88951a48febed47/BLOG-2422_7.png" />
          </figure>
    <div>
      <h2>What’s next? </h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>What we’re offering today for Speed Brain is only the beginning. Heading into 2025, we have a number of exciting additions to explore and ship. </p>
    <div>
      <h3>Leveraging Machine Learning</h3>
      <a href="#leveraging-machine-learning">
        
      </a>
    </div>
    <p>Our unique position on the Internet provides us valuable insights into web browsing patterns, which we can leverage for improving web performance while maintaining individual user privacy. By employing a generalized data-driven machine learning approach, we can define more accurate and site-specific prefetch predictors for users’ pages. </p><p>We are in the process of developing an adaptive speculative model that significantly improves upon our current conservative offering. This model uses a privacy-preserving method to generate a user traversal graph for each site based on same-site Referrer headers. For any two pages connected by a navigational hop, our model predicts the likelihood of a typical user moving between them, using insights extracted from our aggregated traffic data.</p><p>This model enables us to tailor rule sets with custom eagerness values to each relevant next page link on your site. For pages where the model predicts high confidence in user navigation, the system will aggressively prefetch or prerender them. If the model does not provide a rule for a page, it defaults to our existing conservative approach, maintaining the benefits of baseline Speed Brain model. These signals guide browsers in prefetching and prerendering the appropriate pages, which helps speed up navigation for users, while maintaining our current safety guardrails.</p><p>In lab tests, our ML model improved LCP latency by 75% and predicted visitor navigation with ~98% accuracy, ensuring the correct pages were being prefetched to prevent resource waste for users. As we move toward scaling this solution, we are focused on periodic training of the model to adapt to varying user behaviors and evolving websites. Using an online machine learning approach will drastically reduce the need for any manual update, and content drifts, while maintaining high accuracy — the Speed Brain load solution that gets smarter over time!</p>
    <div>
      <h3>Finer observability via RUM</h3>
      <a href="#finer-observability-via-rum">
        
      </a>
    </div>
    <p>As we’ve mentioned, we believe that our RUM tools offer the best insights for how Speed Brain is helping the performance of your website. In the future, we plan on offering the ability to filter RUM tooling by navigation type so that you can compare the browser rendering of prefetched content versus non-prefetched content. </p>
    <div>
      <h3>Prerendering</h3>
      <a href="#prerendering">
        
      </a>
    </div>
    <p>We are currently offering the ability for prefetching on cacheable content. Prefetching downloads the main document resource of the page before the user’s navigation, but it does not instruct the browser to prerender the page or download any additional subresources.</p><p>In the future, Cloudflare’s Speed Brain offering will prefetch content into our CDN cache and then work with browsers to know what are the best prospects for prerendering. This will help get static content even closer to instant rendering. </p>
    <div>
      <h3>Argo Smart Browsing: Speed Brain &amp; Smart Routing</h3>
      <a href="#argo-smart-browsing-speed-brain-smart-routing">
        
      </a>
    </div>
    <p>Speed Brain, in its initial implementation, provides an incredible performance boost whilst still remaining conservative in its implementation; both from an eagerness, and a resource consumption perspective.</p><p>As was outlined earlier in the post, lab testing of a more aggressive model, powered by machine-learning and a higher eagerness, yielded a <b>75% reduction in LCP.</b> We are investigating bundling this more aggressive, additional implementation of Speed Brain with Argo Smart Routing into a product called <b>“Argo Smart Browsing”. </b></p><p>Cloudflare customers will be free to continue using Speed Brain, however those who want even more performance improvement will be able to enable Argo Smart Browsing with a single button click.  With Argo Smart Browsing, not only will cacheable static content load up to 75% faster in the browser, thanks to the more aggressive models, however in times when content can’t be cached, and the request must go forward to an origin server, it will be sent over the most performant network path resulting in an average <b>33% performance increase.</b> Performance optimizations are being applied to almost every segment of the request lifecycle regardless if the content is static or dynamic, cached or not. </p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>To get started with Speed Brain, navigate to <a href="https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization/content"><b><u>Speed</u></b><u> &gt; Optimization &gt; Content Optimization &gt; </u><b><u>Speed Brain</u></b></a> in the Cloudflare Dashboard and enable it. That's all! The feature can also be enabled via <a href="https://developers.cloudflare.com/api/operations/zone-settings-get-speed-brain-setting"><u>API</u></a>.  Free plan domains have had Speed Brain enabled by default.</p><p>We strongly recommend that customers also <a href="https://developers.cloudflare.com/web-analytics/get-started/#sites-proxied-through-cloudflare"><b><u>enable RUM</u></b></a>, found in the same section of the dashboard, to give visibility into the performance improvements provided by Speed Brain and other Cloudflare features and products. </p><p>We’re excited to continue to build products and features that make web performance reliably fast. If you’re an engineer interested in improving the performance of the web for all, <a href="http://cloudflare.com/jobs">come join us</a>!</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/OaN8mrrAKAatOUCqGAsqu/15ac363626180a0f0ed1a0cdb8146e5f/BLOG-2422_8.png" />
          </figure>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed Brain]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">sC3G9YR2M9IIoRMg8slDl</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator>Suleman Ahmad</dc:creator>
            <dc:creator>William Woodhead</dc:creator>
        </item>
        <item>
            <title><![CDATA[Instant Purge: invalidating cached content in under 150ms]]></title>
            <link>https://blog.cloudflare.com/instant-purge/</link>
            <pubDate>Tue, 24 Sep 2024 23:00:00 GMT</pubDate>
            <description><![CDATA[ We’ve built the fastest cache purge in the industry by offering a global purge latency for purge by tags, hostnames, and prefixes of less than 150ms on average (P50), representing a 90% improvement.  ]]></description>
            <content:encoded><![CDATA[ <p><sup>(part 3 of the Coreless Purge </sup><a href="https://blog.cloudflare.com/rethinking-cache-purge-architecture/"><sup>series</sup></a><sup>)</sup></p><p>Over the past 14 years, Cloudflare has evolved far beyond a Content Delivery Network (CDN), expanding its offerings to include a comprehensive <a href="https://developers.cloudflare.com/cloudflare-one/"><u>Zero Trust</u></a> security portfolio, network security &amp; performance <a href="https://www.cloudflare.com/network-services/products/"><u>services</u></a>, application security &amp; performance <a href="https://www.cloudflare.com/application-services/products/"><u>optimizations</u></a>, and a powerful <a href="https://www.cloudflare.com/developer-platform/products/"><u>developer platform</u></a>. But customers also continue to rely on Cloudflare for caching and delivering static website content. CDNs are often judged on their ability to return content to visitors as quickly as possible. However, the speed at which content is removed from a CDN's global cache is just as crucial.</p><p>When customers frequently update content such as news, scores, or other data, it is essential they<a href="https://www.cloudflare.com/learning/cdn/common-cdn-issues/"> avoid serving stale, out-of-date information</a> from cache to visitors. This can lead to a <a href="https://www.cloudflare.com/learning/cdn/common-cdn-issues/">subpar experience</a> where users might see invalid prices, or incorrect news. The goal is to remove the stale content and cache the new version of the file on the CDN, as quickly as possible. And that starts by issuing a “purge.”</p><p>In May 2022, we released the <a href="https://blog.cloudflare.com/part1-coreless-purge/"><u>first part</u><b><u> </u></b></a>of the series detailing our efforts to rebuild and publicly document the steps taken to improve the system our customers use, to purge their cached content. Our goal was to increase scalability, and importantly, the speed of our customer’s purges. In that initial post, we explained how our purge system worked and the design constraints we found when scaling. We outlined how after more than a decade, we had outgrown our purge system and started building an entirely new purge system, and provided purge performance benchmarking that users experienced at the time. We set ourselves a lofty goal: to be the fastest.</p><p><b>Today, we’re excited to share that we’ve built the fastest cache purge in the industry.</b>  We now offer a global purge latency for purge by tags, hostnames, and prefixes of less than 150ms on average (P50), representing a 90% improvement since May 2022. Users can now purge from anywhere, (almost) <i>instantly</i>. By the time you hit enter on a purge request and your eyes blink, the file is now removed from our global network — including data centers in <a href="https://www.cloudflare.com/network/"><u>330 cities</u></a> and <a href="https://blog.cloudflare.com/backbone2024/"><u>120+ countries</u></a>.</p><p>But that’s not all. It wouldn’t be Birthday Week if we stopped at just being the fastest purge. We are <b><i>also</i></b><i> </i>announcing that we’re opening up more purge options to Free, Pro, and Business plans. Historically, only Enterprise customers had access to the full arsenal of <a href="https://developers.cloudflare.com/cache/how-to/purge-cache/"><u>cache purge methods</u></a> supported by Cloudflare, such as purge by cache-tags, hostnames, and URL prefixes. As part of rebuilding our purge infrastructure, we’re not only fast but we are able to scale well beyond our current capacity. This enables more customers to use different types of purge. We are excited to offer these new capabilities to all plan types once we finish rolling out our new purge infrastructure, and expect to begin offering additional purge capabilities to all plan types in early 2025. </p>
    <div>
      <h3>Why cache and purge? </h3>
      <a href="#why-cache-and-purge">
        
      </a>
    </div>
    <p>Caching content is like pulling off a spectacular magic trick. It makes loading website content lightning-fast for visitors, slashes the load on origin servers and the cost to operate them, and enables global scalability with a single button press. But here's the catch: for the magic to work, caching requires predicting the future. The right content needs to be cached in the right data center, at the right moment when requests arrive, and in the ideal format. This guarantees astonishing performance for visitors and game-changing scalability for web properties.</p><p>Cloudflare helps make this caching magic trick easy. But regular users of our cache know that getting content into cache is only part of what makes it useful. When content is updated on an origin, it must also be updated in the cache. The beauty of caching is that it holds content until it expires or is evicted. To update the content, it must be actively removed and updated across the globe quickly and completely. If data centers are not uniformly updated or are updated at drastically different times, visitors risk getting different data depending on where they are located. This is where cache “purging” (also known as “cache invalidation”) comes in.</p>
    <div>
      <h3>One-to-many purges on Cloudflare</h3>
      <a href="#one-to-many-purges-on-cloudflare">
        
      </a>
    </div>
    <p>Back in <a href="https://blog.cloudflare.com/rethinking-cache-purge-architecture/"><u>part 2 of the blog series</u></a>, we touched on how there are multiple ways of purging cache: by URL, cache-tag, hostname, URL prefix, and “purge everything”, and discussed a necessary distinction between purging by URL and the other four kinds of purge — referred to as flexible purges — based on the scope of their impact.</p><blockquote><p><i>The reason flexible purge isn’t also fully coreless yet is because it’s a more complex task than “purge this object”; flexible purge requests can end up purging multiple objects – or even entire zones – from cache. They do this through an entirely different process that isn’t coreless compatible, so to make flexible purge fully coreless we would have needed to come up with an entirely new multi-purge mechanism on top of redesigning distribution. We chose instead to start with just purge by URL, so we could focus purely on the most impactful improvements, revamping distribution, without reworking the logic a data center uses to actually remove an object from cache.</i></p></blockquote><p>We said our next steps included a redesign of flexible purges at Cloudflare, and today we’d like to walk you through the resulting system. But first, a brief history of flexible cache purges at Cloudflare and elaboration on why the old flexible purge system wasn’t “coreless compatible”.</p>
    <div>
      <h3>Just in time</h3>
      <a href="#just-in-time">
        
      </a>
    </div>
    <p>“Cache” within a given data center is made up of many machines, all contributing disk space to store customer content. When a request comes in for an asset, the URL and headers are used to calculate a <a href="https://developers.cloudflare.com/cache/how-to/cache-keys/"><u>cache key</u></a>, which is the filename for that content on disk and also determines which machine in the datacenter that file lives on. The filename is the same for every data center, and every data center knows how to use it to find the right machine to cache the content. A <a href="https://developers.cloudflare.com/cache/how-to/purge-cache/"><u>purge request</u></a> for a URL (plus headers) therefore contains everything needed to generate the cache key — the pointer to the response object on disk — and getting that key to every data center is the hardest part of carrying out the purge.</p><p>Purging content based on response properties has a different hardest part. If a customer wants to purge all content with the cache-tag “foo”, for example, there’s no way for us to generate all the cache keys that will point to the files with that cache-tag at request time. Cache-tags are response headers, and the decision of where to store a file is based on request attributes only. To find all files with matching cache-tags, we would need to look at every file in every cache disk on every machine in every data center. That’s thousands upon thousands of machines we would be scanning for each purge-by-tag request. There are ways to avoid actually continuously scanning all disks worldwide (foreshadowing!) but for our first implementation of our flexible purge system, we hoped to avoid the problem space altogether.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7n56ZDJwdBbaTNPJII6s2S/db998973efdca121536a932bc50dd842/image5.png" />
            
            </figure><p>An alternative approach to going to every machine and looking for all files that match some criteria to actively delete from disk was something we affectionately referred to as “lazy purge”. Instead of deleting all matching files as soon as we process a purge request, we wait to do so when we get an end user request for one of those files. Whenever a request comes in, and we have the file in cache, we can compare the timestamp of any recent purge requests from the file owner to the insertion timestamp of the file we have on disk. If the purge timestamp is fresher than the insertion timestamp, we pretend we didn’t find the file on disk. For this to work, we needed to keep track of purge requests going back further than a data center’s maximum cache eviction age to be sure that any file a customer sends a matching flex purge to clear from cache will either be <a href="https://developers.cloudflare.com/cache/concepts/retention-vs-freshness/#retention"><u>naturally evicted</u></a>, or forced to cache MISS and get refreshed from the origin. With this approach, we just needed a distribution and storage system for keeping track of flexible purges.</p>
    <div>
      <h3>Purge looks a lot like a nail</h3>
      <a href="#purge-looks-a-lot-like-a-nail">
        
      </a>
    </div>
    <p>At Cloudflare there is a lot of configuration data that needs to go “everywhere”: cache configuration, load balancer settings, firewall rules, host metadata — countless products, features, and services that depend on configuration data that’s managed through Cloudflare’s control plane APIs. This data needs to be accessible by every machine in every datacenter in our network. The vast majority of that data is distributed via <a href="https://blog.cloudflare.com/introducing-quicksilver-configuration-distribution-at-internet-scale/"><u>a system introduced several years ago called Quicksilver</u></a>. The system works <i>very, very well</i> (sub-second p99 replication lag, globally). It’s extremely flexible and reliable, and reads are lightning fast. The team responsible for the system has done such a good job that Quicksilver has become a hammer that when wielded, makes everything look like a nail… like flexible purges.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/BFntOlvapsYYjYTcxMs7o/d73ad47b63b9d4893b46aeddc28a8698/image2.png" />
            
            </figure><p><sup><i>Core-based purge request entering a data center and getting backhauled to a core data center where Quicksilver distributes the request to all network data centers (hub and spoke).</i></sup><sup> </sup></p><p>Our first version of the flexible purge system used Quicksilver’s spoke-hub distribution to send purges from a core data center to every other data center in our network. It took less than a second for flexible purges to propagate, and once in a given data center, the purge key lookups in the hot path to force cache misses were in the low hundreds of microseconds. We were quite happy with this system at the time, especially because of the simplicity. Using well-supported internal infrastructure meant we weren’t having to manage database clusters or worry about transport between data centers ourselves, since we got that “for free”. Flexible purge was a new feature set and the performance seemed pretty good, especially since we had no predecessor to compare against.</p>
    <div>
      <h3>Victims of our own success</h3>
      <a href="#victims-of-our-own-success">
        
      </a>
    </div>
    <p>Our first version of flexible purge didn’t start showing cracks for years, but eventually both our network and our customer base grew large enough that our system was reaching the limits of what it could scale to. As mentioned above, we needed to store purge requests beyond our maximum eviction age. Purge requests are relatively small, and compress well, but thousands of customers using the API millions of times a day adds up to quite a bit of storage that Quicksilver needed on each machine to maintain purge history, and all of that storage cut into disk space we could otherwise be using to cache customer content. We also found the limits of Quicksilver in terms of how many writes per second it could handle without replication slowing down. We bought ourselves more runway by putting <a href="https://www.boltic.io/blog/kafka-queue#:~:text=Apache%20Kafka%20Queues%3F-,Apache%20Kafka%20queues,-are%20a%20powerful"><u>Kafka queues</u></a> in front of Quicksilver to buffer and throttle ourselves to even out traffic spikes, and increased batching, but all of those protections introduced latency. We knew we needed to come up with a solution without such a strong correlation between usage and operational costs.</p><p>Another pain point exposed by our growing user base that we mentioned in <a href="https://blog.cloudflare.com/rethinking-cache-purge-architecture/"><u>Part 2</u></a> was the excessive round trip times experienced by customers furthest away from our core data centers. A purge request sent by a customer in Australia would have to cross the Pacific Ocean and back before local customers would see the new content.</p><p>To summarize, three issues were plaguing us:</p><ol><li><p>Latency corresponding to how far a customer was from the centralized ingest point.</p></li><li><p>Latency due to the bottleneck for writes at the centralized ingest point.</p></li><li><p>Storage needs in all data centers correlating strongly with throughput demand.</p></li></ol>
    <div>
      <h3>Coreless purge proves useful</h3>
      <a href="#coreless-purge-proves-useful">
        
      </a>
    </div>
    <p>The first two issues affected all types of purge. The spoke-hub distribution model was problematic for purge-by-URL just as much as it was for flexible purges. So we embarked on the path to peer-to-peer distribution for purge-by-URL to address the latency and throughput issues, and the results of that project were good enough that we wanted to propagate flexible purges through the same system. But doing so meant we’d have to replace our use of Quicksilver; it was so good at what it does (fast/reliable replication network-wide, extremely fast/high read throughput) in large part because of the core assumption of spoke-hub distribution it could optimize for. That meant there was no way to write to Quicksilver from “spoke” data centers, and we would need to find another storage system for our purges.</p>
    <div>
      <h3>Flipping purge on its head</h3>
      <a href="#flipping-purge-on-its-head">
        
      </a>
    </div>
    <p>We decided if we’re going to replace our storage system we should dig into exactly what our needs are and find the best fit. It was time to revisit some of our oldest conclusions to see if they still held true, and one of the earlier ones was that proactively purging content from disk would be difficult to do efficiently given our storage layout.</p><p>But was that true? Or could we make active cache purge fast and efficient (enough)? What would it take to quickly find files on disk based on their metadata? “Indexes!” you’re probably screaming, and for good reason. Indexing files’ hostnames, cache-tags, and URLs would undoubtedly make querying for relevant files trivial, but a few aspects of our network make it less straightforward.</p><p>Cloudflare has hundreds of data centers that see trillions of unique files, so any kind of global index — even ignoring the networking hurdles of aggregation — would suffer the same type of bottlenecking issues with our previous spoke-hub system. Scoping the indices to the data center level would be better, but they vary in size up to several hundred machines. Managing a database cluster in each data center scaled to the appropriate size for the aggregate traffic of all the machines was a daunting proposition; it could easily end up being enough work on its own for a separate team, not something we should take on as a side hustle.</p><p>The next step down in scope was an index per machine. Indexing on the same machine as the cache proxy had some compelling upsides: </p><ul><li><p>The proxy could talk to the index over <a href="https://en.wikipedia.org/wiki/Unix_domain_socket"><u>UDS</u></a> (Unix domain sockets), avoiding networking complexities in the hottest paths.</p></li><li><p>As a sidecar service, the index just had to be running anytime the machine was accepting traffic. If a machine died, so would the index, but that didn’t matter, so there wasn’t any need to deal with the complexities of distributed databases.</p></li><li><p>While data centers were frequently adding and removing machines, machines weren’t frequently adding and removing disks. An index could reasonably count on its maximum size being predictable and constant based on overall disk size.</p></li></ul><p>But we wanted to make sure it was feasible on our machines. We analyzed representative cache disks from across our fleet, gathering data like the number of cached assets per terabyte and the average number of cache-tags per asset. We looked at cache MISS, REVALIDATED, and EXPIRED rates to estimate the required write throughput.</p><p>After conducting a thorough analysis, we were convinced the design would work. With a clearer understanding of the anticipated read/write throughput, we started looking at databases that could meet our needs. After benchmarking several relational and non-relational databases, we ultimately chose <a href="https://github.com/facebook/rocksdb"><u>RocksDB</u></a>, a high-performance embedded key-value store. We found that with proper tuning, it could be extremely good at the types of queries we needed.</p>
    <div>
      <h3>Putting it all together</h3>
      <a href="#putting-it-all-together">
        
      </a>
    </div>
    <p>And so CacheDB was born — a service written in Rust and built on RocksDB, which operates on each machine alongside the cache proxy to manage the indexing and purging of cached files. We integrated the cache proxy with CacheDB to ensure that indices are stored whenever a file is cached or updated, and they’re deleted when a file is removed due to eviction or purging. In addition to indexing data, CacheDB maintains a local queue for buffering incoming purge operations. A background process reads purge operations in the queue, looking up all matching files using the indices, and deleting the matched files from disk. Once all matched files for an operation have been deleted, the process clears the indices and removes the purge operation from the queue.</p><p>To further optimize the speed of purges taking effect, the cache proxy was updated to check with CacheDB — similar to the previous lazy purge approach — when a cache HIT occurs before returning the asset. CacheDB does a quick scan of its local queue to see if there are any pending purge operations that match the asset in question, dictating whether the cache proxy should respond with the cached file or fetch a new copy. This means purges will prevent the cache proxy from returning a matching cached file as soon as a purge reaches the machine, even if there are millions of files that correspond to a purge key, and it takes a while to actually delete them all from disk.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5W0ZIGBBbG5Cnc3DSbCPGT/a1572b0b67d844d4e5b7cc7899d320b1/image3.png" />
            
            </figure><p><sup><i>Coreless purge using CacheDB and Durable Objects to distribute purges without needing to first stop at a core data center.</i></sup></p><p>The last piece to change was the distribution pipeline, updated to broadcast flexible purges not just to every data center, but to the CacheDB service running on every machine. We opted for CacheDB to handle the last-mile fan out of machine to machine within a data center, using <a href="https://www.consul.io/"><u>consul</u></a> to keep each machine informed of the health of its peers. The choice let us keep the Workers largely the same for purge-by-URL (more <a href="https://blog.cloudflare.com/rethinking-cache-purge-architecture/"><u>here</u></a>) and flexible purge handling, despite the difference in termination points.</p>
    <div>
      <h3>The payoff</h3>
      <a href="#the-payoff">
        
      </a>
    </div>
    <p>Our new approach reduced the long tail of the lazy purge, saving 10x storage. Better yet, we can now delete purged content immediately instead of waiting for the lazy purge to happen or expire. This new-found storage will improve cache retention on disk for all users, leading to improved cache HIT ratios and reduced egress from your origin.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6B0kVX9Q6qA2JshmcTZSrt/80a845904adf8ba69c121bb54923959e/image1.png" />
            
            </figure><p><sup><i>The shift from lazy content purging (</i></sup><sup><i><u>left</u></i></sup><sup><i>) to the new Coreless Purge architecture allows us to actively delete content (</i></sup><sup><i><u>right</u></i></sup><sup><i>). This helps reduce storage needs and increase cache retention times across our service.</i></sup></p><p>With the new coreless cache purge, we can now get a purge request into any datacenter, distribute the keys to purge, and instantly purge the content from the cache database. This all occurs in less than 150 milliseconds on P50 for tags, hostnames, and prefix URL, covering all <a href="https://www.cloudflare.com/network/"><u>330 cities</u></a> in <a href="https://blog.cloudflare.com/backbone2024/"><u>120+ countries</u></a>.</p>
    <div>
      <h3>Benchmarks</h3>
      <a href="#benchmarks">
        
      </a>
    </div>
    <p>To measure Instant Purge, we wanted to make sure that we were looking at real user metrics — that these were purges customers were actually issuing and performance that was representative of what we were seeing under real conditions, rather than marketing numbers.</p><p>The time we measure represents the period when a request enters the local datacenter, and ends with when the purge has been executed in every datacenter. When the local data center receives the request, one of the first things we do is to add a timestamp to the purge request. When all data centers have completed the purge action, another timestamp is added to “stop the clock.” Each purge request generates this performance data, and it is then sent to a database for us to measure the appropriate quantiles and to help us understand how we can improve further.</p><p>In August 2024, we took purge performance data and segmented our collected data by region based on where the local data center receiving the request was located.</p><table><tr><td><p><b>Region</b></p></td><td><p><b>P50 Aug 2024 (Coreless)</b></p></td><td><p><b>P50 May 2022 (Core-based)</b></p></td><td><p><b>Improvement</b></p></td></tr><tr><td><p>Africa</p></td><td><p>303ms</p></td><td><p>1,420ms</p></td><td><p>78.66%</p></td></tr><tr><td><p>Asia Pacific Region (APAC)</p></td><td><p>199ms</p></td><td><p>1,300ms</p></td><td><p>84.69%</p></td></tr><tr><td><p>Eastern Europe (EEUR)</p></td><td><p>140ms</p></td><td><p>1,240ms</p></td><td><p>88.70%</p></td></tr><tr><td><p>Eastern North America (ENAM)</p></td><td><p>119ms</p></td><td><p>1,080ms</p></td><td><p>88.98%</p></td></tr><tr><td><p>Oceania</p></td><td><p>191ms</p></td><td><p>1,160ms</p></td><td><p>83.53%</p></td></tr><tr><td><p>South America (SA)</p></td><td><p>196ms</p></td><td><p>1,250ms</p></td><td><p>84.32%</p></td></tr><tr><td><p>Western Europe (WEUR)</p></td><td><p>131ms</p></td><td><p>1,190ms</p></td><td><p>88.99%</p></td></tr><tr><td><p>Western North America (WNAM)</p></td><td><p>115ms</p></td><td><p>1,000ms</p></td><td><p>88.5%</p></td></tr><tr><td><p><b>Global</b></p></td><td><p><b>149ms</b></p></td><td><p><b>1,570ms</b></p></td><td><p><b>90.5%</b></p></td></tr></table><p><sup>Note: Global latency numbers on the core-based measurements (May 2022) may be larger than the regional numbers because it represents all of our data centers instead of only a regional portion, so outliers and retries might have an outsized effect.</sup></p>
    <div>
      <h3>What’s next?</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>We are currently wrapping up the roll-out of the last throughput changes which allow us to efficiently scale purge requests. As that happens, we will revise our rate limits and open up purge by tag, hostname, and prefix to all plan types! We expect to begin rolling out the additional purge types to all plans and users beginning in early <b>2025</b>.</p><p>In addition, in the process of implementing this new approach, we have identified improvements that will shave a few more milliseconds off our single-file purge. Currently, single-file purges have a P50 of 234ms. However, we want to, and can, bring that number down to below 200ms.</p><p>If you want to come work on the world's fastest purge system, check out <a href="http://www.cloudflare.com/careers">our open positions</a>.</p>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">11EWaw0wCUNwPTM30w7oUN</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator>Tim Kornhammar</dc:creator>
            <dc:creator> Connor Harwood</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cache Rules are now GA: precision control over every part of your cache]]></title>
            <link>https://blog.cloudflare.com/cache-rules-go-ga/</link>
            <pubDate>Tue, 24 Oct 2023 13:00:40 GMT</pubDate>
            <description><![CDATA[ Today, we're thrilled to share that Cache Rules, along with several other Rules products, are generally available (GA). But that’s not all — we're also introducing new configuration options for Cache Rules ]]></description>
            <content:encoded><![CDATA[ <p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/23yqkja301zV4TfUtTrL0D/1619ec8778be0841f28ddd0fc07a03ba/Cache-Rules-GA-1.png" />
            
            </figure><p>One year ago we introduced Cache Rules, a new way to customize cache settings on Cloudflare. Cache Rules provide greater flexibility for how users cache content, offering precise controls, a user-friendly API, and seamless Terraform integrations. Since it was released in late September 2022, over 100,000 websites have used Cache Rules to fine-tune their cache settings.</p><p>Today, we're thrilled to announce that Cache Rules, along with several other <a href="https://developers.cloudflare.com/rules/">Rules products</a>, are <b>generally available (GA)</b>. But that’s not all — we're also introducing new configuration options for Cache Rules that provide even more options to customize how you cache on Cloudflare. These include functionality to define what resources are eligible for <a href="https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/">Cache Reserve</a>, what <a href="https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#error-524-a-timeout-occurred">timeout values</a> should be respected when receiving data from your origin server, which <a href="https://developers.cloudflare.com/fundamentals/reference/network-ports/#network-ports-compatible-with-cloudflares-proxy">custom ports</a> we should use when we cache content, and whether we should bypass Cloudflare’s cache in the absence of a <a href="https://developers.cloudflare.com/cache/concepts/cache-control/#cache-control-directives">cache-control</a> header.</p><p>Cache Rules give users full control and the ability to tailor their content delivery strategy for almost any use case, without needing to write code. As Cache Rules go GA, we are incredibly excited to see how fast customers can achieve their perfect cache strategy.</p>
    <div>
      <h3>History of Customizing Cache on Cloudflare</h3>
      <a href="#history-of-customizing-cache-on-cloudflare">
        
      </a>
    </div>
    <p>The journey of <a href="https://www.cloudflare.com/learning/cdn/what-is-caching/">cache</a> customization on Cloudflare began more than a decade ago, right at the beginning of the company. From the outset, one of the most frequent requests from our customers involved simplifying their configurations. Customers wanted to easily implement precise cache policies, apply robust security measures, manipulate headers, set up redirects, and more for any page on their website. Using Cloudflare to set these controls was especially crucial for customers utilizing origin servers that only provided convoluted configuration options to add headers or policies to responses, which could later be applied downstream by <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDNs</a>.</p><p>In response to this demand, we introduced Page Rules, a product that has since witnessed remarkable growth in both its popularity and functionality. Page Rules became the preferred choice for customers seeking granular control over how Cloudflare caches their content. Currently, there are over 5 million active cache-related Page Rules, assisting websites in tailoring their content delivery strategies.</p><p>However, behind the scenes, Page Rules encountered a scalability issue.</p><p>Whenever a Page Rule is encountered by Cloudflare we must transform all rule conditions for a customer into a single regex pattern. This pattern is then applied to requests for the website to achieve the desired cache configuration. When thinking about how all the regexes from all customers are then compared against tens of millions of requests per second, spanning across more than 300 data centers worldwide, it’s easy to see that the computational demands for applying Page Rules can be immense. This pressure is directly tied to the number of rules we could offer our users. For example, Page Rules would only allow for 125 rules to be deployed on a given website.</p><p>To address this challenge, we rebuilt all the Page Rule functionality on the new <a href="https://developers.cloudflare.com/ruleset-engine/">Rulesets Engine</a>. Not only do ruleset engine-based products give users more rules to play with, they also offer greater flexibility on when these rules should run. Part of the magic of the Rulesets engine is that rather than combine all of a page's rules into a single regular expression, rule logic can be evaluated on a conditional basis. For example, if <a href="https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-subdomain/">subdomain</a> A and B have different caching policies, a request from subdomain A can be evaluated using regex logic specific to A (while omitting any logic that applies to B). This yields meaningful benefits to performance, and reduces the computational demands of applying Page Rules across Cloudflare's network.</p><p>Over the past year, Cache Rules, along with Origin Rules, Configuration Rules, and Single Redirect Rules, have been in beta. Thanks to the invaluable support of our early adopters, we have successfully fine-tuned our product, reaching a stage where it is ready to transition from beta to GA. These products can now accomplish everything that Page Rules could and more. This also marks the beginning of the <a href="https://en.wikipedia.org/wiki/End-of-life_product">EOL</a> process for Page Rules. In the coming months we will announce timelines and information regarding how customers will replace their Page Rules with specific Rules products. We will automate this as much as possible and provide simple steps to ensure a smooth transition away from Page Rules for everyone.</p>
    <div>
      <h3>How to use Cache Rules and What’s New</h3>
      <a href="#how-to-use-cache-rules-and-whats-new">
        
      </a>
    </div>
    <p>Those that have used Cache Rules know that they are intuitive and work similarly to our other <a href="https://developers.cloudflare.com/ruleset-engine/">ruleset engine</a> products. User-defined criteria like URLs or request headers are evaluated, and if matching a specified value, the Cloudflare caching configuration is obeyed. Each Cache Rule depends on fields, operators, and values. For all the different options available, you should see our Cache Rules <a href="https://developers.cloudflare.com/cache/about/cache-rules/">documentation</a>.</p><p>Below are two examples of how to deploy different strategies to customize your cache. These examples only show the tip-of-the-iceberg of what’s possible with Cache Rules, so we encourage you to try them out and let us know what you think.</p>
    <div>
      <h4>Example: Cached content is updated at a regular cadence</h4>
      <a href="#example-cached-content-is-updated-at-a-regular-cadence">
        
      </a>
    </div>
    <p>As an example, let’s say that Acme Corp wants to update their caching strategy. They want to customize their cache to take advantage of certain request headers and use the presence of those request headers to be the criteria that decides when to apply different cache rules. The first thing they’d need to decide is what information should be used to trigger the specific rule. This is defined in the <a href="https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/">expression</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2kfN0DJOJ9myEPesXCu6fw/7218e39e9ffbaa96d6ae0e96e6a4862d/Screenshot-2023-10-18-at-6.27.59-PM.png" />
            
            </figure><p>Once the triggering criteria is defined Acme Corp should next determine how they want to customize their cache.</p>
    <div>
      <h4>Content changing quickly</h4>
      <a href="#content-changing-quickly">
        
      </a>
    </div>
    <p>The most common cache strategy is to update the <a href="https://developers.cloudflare.com/cache/how-to/cache-rules/#create-cache-rules-in-the-dashboard">Edge Cache TTL</a>. If Acme Corp thinks a particular piece of content on their website might change quickly, they can alter the time Cloudflare should consider a resource eligible to be served from cache to be shorter. This way Cloudflare would go back to the origin more frequently to <a href="https://developers.cloudflare.com/cache/concepts/cache-control/#:~:text=If%20the%20content%20is%20stale%20in%20Cloudflare%E2%80%99s%20cache%2C%20Cloudflare%20attempts%20to%20revalidate%20the%20content%20with%20the%20origin%20before%20serving%20the%20response%20to%20the%20client.">revalidate and update the content</a>. The Edge Cache TTL section is also where Acme Corp can define a resource’s TTL based on the status code Cloudflare gets back from their origin, and what Cloudflare should cache if there aren’t any cache-control instructions sent from Acme’s origin server.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2swqQzRX7v3UropZSNRbjH/86bac883296e8c5502e6b5a08e5b5df9/Screenshot-2023-10-08-at-4.14.17-PM.png" />
            
            </figure>
    <div>
      <h4>Content changing slowly</h4>
      <a href="#content-changing-slowly">
        
      </a>
    </div>
    <p>On the other hand, if Acme Corp had a lot of content that did not change very frequently (like a favicon or logo) and they preferred to serve that from Cloudflare’s cache instead of their origin, they can define which content should be eligible for <a href="https://developers.cloudflare.com/cache/advanced-configuration/cache-reserve/">Cache Reserve</a> with a new Cache Rule. Cache Reserve reduces egress fees by storing assets persistently in Cloudflare's cache for an extended period of time.</p><p>Traditionally when a user would enable Cache Reserve, their entire zone would be eligible to be written to Cache Reserve. For customers that care about saving origin <a href="https://www.cloudflare.com/learning/cloud/what-are-data-egress-fees/">egress fees</a> on all resources on their website, this is still the best path forward. But for customers that want to have additional control over precisely what assets should be part of their Cache Reserve or even what size of assets should be eligible, the Cache Reserve Eligibility Rule provides additional knobs so that customers can precisely increase their cache hits and reduce origin egress in a customized manner. Note that this rule requires a Cache Reserve subscription.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7b22znoAtsYBjMbufZhP9q/04b5ab28becee5d25d87f558efc1cb44/Screenshot-2023-10-08-at-4.14.48-PM.png" />
            
            </figure>
    <div>
      <h3>Example: Origin is slow</h3>
      <a href="#example-origin-is-slow">
        
      </a>
    </div>
    <p>Let’s consider a hypothetical example. Recently, Acme Corp has been seeing an increase in errors in their Cloudflare logs. These errors are related to a new report that Acme is providing its users based on Acme’s proprietary data. This report requires that their origin access several databases, perform some calculations and generate the report based on these calculations. The origin generating this report needs to wait to respond until all of this background work is completed. Acme’s report is a success, generating an influx of traffic from visitors wanting to see it. But their origin is struggling to keep up. A lot of the errors they are seeing are 524s which correlate to Cloudflare not seeing an origin response before a timeout occurred.</p><p>Acme has plans to improve this by scaling their origin infrastructure but it’s taking a long time to deploy. In the meantime, they can turn to Cache Rules to configure a timeout to be longer. Historically the timeout value between Cloudflare and two successive origin reads was 100 seconds, which meant that if an origin didn't successfully send a response for a period lasting longer than 100 seconds, it could lead to a 524 error. By using a Cache Rule to extend this timeout, Acme Corp can rely more heavily on Cloudflare's cache.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1XqipB1JsifcQLUyGn40BB/5bc7e324c62ab607e2c30c665849f67b/Screenshot-2023-10-18-at-6.21.32-PM.png" />
            
            </figure><p>The above cache strategies focus on how often a resource is changed on an origin, and the origin’s performance. But there are numerous other rules that allow for other strategies, like <a href="https://developers.cloudflare.com/cache/how-to/cache-keys/">custom cache keys</a> which allow for customers to determine how their cache should be defined on Cloudflare, respecting <a href="https://developers.cloudflare.com/cache/reference/etag-headers/">strong ETags</a> which help customers determine when Cloudflare should revalidate particular cached assets, and custom ports which allow for customers to define <a href="https://developers.cloudflare.com/fundamentals/reference/network-ports/#network-ports-compatible-with-cloudflares-proxy">non-standard ports</a> that Cloudflare should use when making caching decisions about content.</p><p>The full list of Cache Rules can be found <a href="https://developers.cloudflare.com/cache/how-to/cache-rules/">here</a>.</p>
    <div>
      <h3>Try Cache Rules today!</h3>
      <a href="#try-cache-rules-today">
        
      </a>
    </div>
    <p>We will continue to build and release additional rules that provide powerful, easy to enable control for anyone using Cloudflare’s cache. If you have feature requests for additional Cache Rules, please let us know in the <a href="https://community.cloudflare.com/">Cloudflare Community</a>.</p><p>Go to the <a href="https://dash.cloudflare.com/caching/cache-rules">dashboard</a> and try Cache Rules out today!</p> ]]></content:encoded>
            <category><![CDATA[General Availability]]></category>
            <category><![CDATA[Cache Rules]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Application Services]]></category>
            <category><![CDATA[Performance]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Connectivity Cloud]]></category>
            <guid isPermaLink="false">4GOWR9PBxeYrH9OGO3zxjZ</guid>
            <dc:creator>Alex Krivit</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare Integrations Marketplace introduces three new partners: Sentry, Momento and Turso]]></title>
            <link>https://blog.cloudflare.com/cloudflare-integrations-marketplace-new-partners-sentry-momento-turso/</link>
            <pubDate>Thu, 28 Sep 2023 13:00:36 GMT</pubDate>
            <description><![CDATA[ We introduced integrations with Supabase, PlanetScale, Neon and Upstash. Today, we are thrilled to introduce our newest additions to Cloudflare’s Integrations Marketplace – Sentry, Turso and Momento ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Building modern full-stack applications requires connecting to many hosted third party services, from observability platforms to databases and more. All too often, this means spending time doing busywork, managing credentials and writing glue code just to get started. This is why we’re building out the Cloudflare Integrations Marketplace to allow developers to easily discover, configure and deploy products to use with Workers.</p><p>Earlier this year, we introduced integrations with <a href="/announcing-database-integrations/">Supabase, PlanetScale, Neon</a> and <a href="/cloudflare-workers-database-integration-with-upstash/">Upstash</a>. Today, we are thrilled to introduce our newest additions to Cloudflare’s Integrations Marketplace – <a href="https://developers.cloudflare.com/workers/observability/sentry-integration/">Sentry</a>, <a href="https://developers.cloudflare.com/workers/databases/native-integrations/turso/">Turso</a> and <a href="https://developers.cloudflare.com/workers/databases/native-integrations/momento/">Momento</a>.</p><p>Let's take a closer look at some of the exciting integration providers that are now part of the Workers Integration Marketplace.</p>
    <div>
      <h3>Improve performance and reliability by connecting Workers to Sentry</h3>
      <a href="#improve-performance-and-reliability-by-connecting-workers-to-sentry">
        
      </a>
    </div>
    <p>When your Worker encounters an error you want to know what happened and exactly what line of code triggered it. <a href="https://sentry.io/welcome/">Sentry</a> is an <a href="https://www.cloudflare.com/application-services/solutions/app-performance-monitoring/">application monitoring</a> platform that helps developers identify and resolve issues in real-time.</p><p>The <a href="https://developers.cloudflare.com/workers/observability/sentry-integration/">Workers and Sentry integration</a> automatically sends errors, exceptions and <code>console.log()</code> messages from your Worker to Sentry with no code changes required. Here’s how it works:</p><ol><li><p>You enable the integration from the Cloudflare Dashboard.</p></li><li><p>The credentials from the Sentry project of your choice are automatically added to your Worker.</p></li><li><p>You can configure <a href="https://docs.sentry.io/platforms/javascript/configuration/sampling/#configuring-the-transaction-sample-rate">sampling</a> to control the volume of events you want sent to Sentry. This includes selecting the sample rate for different status codes and exceptions.</p></li><li><p>Cloudflare deploys a <a href="https://developers.cloudflare.com/workers/observability/tail-workers/">Tail Worker</a> behind the scenes that contains all the logic needed to capture and send data to Sentry.</p></li><li><p>Like magic, errors, exceptions, and log messages are automatically sent to your Sentry project.</p></li></ol><p>In the future, we’ll be improving this integration by adding support for uploading source maps and stack traces so that you can pinpoint exactly which line of your code caused the issue. We’ll also be tying in <a href="https://developers.cloudflare.com/workers/configuration/deployments/">Workers deployments</a> with <a href="https://docs.sentry.io/product/releases/">Sentry releases</a> to correlate new versions of your Worker with events in Sentry that help pinpoint problematic deployments. Check out our <a href="https://developers.cloudflare.com/workers/observability/sentry-integration/">developer documentation</a> for more information.</p>
    <div>
      <h3>Develop at the Data Edge with Turso + Workers</h3>
      <a href="#develop-at-the-data-edge-with-turso-workers">
        
      </a>
    </div>
    <p><a href="https://turso.tech/">Turso</a> is an edge-hosted, distributed database based on libSQL, an open-source fork of SQLite. Turso focuses on providing a global service that minimizes query latency (and thus, application latency!). It’s perfect for use with Cloudflare Workers – both compute and data are served close to users.</p><p>Turso follows the model of having one primary database with replicas that are located globally, close to users. Turso automatically routes requests to a replica closest to where the Worker was invoked. This model works very efficiently for read heavy applications since read requests can be served globally. If you’re running an application that has heavy write workloads, or want to cut down on replication costs, you can run Turso with just the <a href="https://docs.turso.tech/concepts#primary">primary</a> instance and use <a href="https://developers.cloudflare.com/workers/configuration/smart-placement/">Smart Placement</a> to speed up queries.</p><p>The Turso and Workers integration automatically pulls in Turso API credentials and adds them as secrets to your Worker, so that you can start using Turso by simply establishing a connection using the <a href="https://www.npmjs.com/package/@libsql/client">libsql SDK</a>. Get started with the Turso and Workers Integration today by heading to our <a href="https://developers.cloudflare.com/workers/databases/native-integrations/turso/">developer documentation</a>.</p>
    <div>
      <h3>Cache responses from data stores with Momento</h3>
      <a href="#cache-responses-from-data-stores-with-momento">
        
      </a>
    </div>
    <p><a href="https://www.gomomento.com/services/cache">Momento Cache</a> is a low latency serverless caching solution that can be used on top of relational databases, key-value databases or object stores to get faster load times and better performance. Momento abstracts details like scaling, warming and replication so that users can deploy cache in a matter of minutes.</p><p>The Momento and Workers integration automatically pulls in your Momento API key using an OAuth2 flow. The Momento API key is added as a secret in Workers and, from there, you can start using the <a href="https://www.npmjs.com/package/@gomomento/sdk">Momento SDK</a> in Workers. Head to our <a href="https://developers.cloudflare.com/workers/databases/native-integrations/momento/">developer documentation</a> to learn more and use the Momento and Workers integration!</p>
    <div>
      <h3>Try integrations out today</h3>
      <a href="#try-integrations-out-today">
        
      </a>
    </div>
    <p>We want to give you back time, so that you can focus less on configuring and connecting third party tools to Workers and spend more time building. We’re excited to see what you build with integrations. Share your projects with us on Twitter (<a href="https://twitter.com/cloudflaredev">@CloudflareDev</a>) and stay tuned for more exciting updates as we continue to grow our Integrations Marketplace!</p><p>If you would like to partner with Cloudflare and build an integration, please fill out the <a href="https://www.cloudflare.com/partners/technology-partners/">partner request form</a> and we'll be in touch.</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Observability]]></category>
            <category><![CDATA[Edge Database]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">HkjVgVT5KZ05Cjk2u6S99</guid>
            <dc:creator>Tanushree Sharma</dc:creator>
        </item>
        <item>
            <title><![CDATA[Reduce latency and increase cache hits with Regional Tiered Cache]]></title>
            <link>https://blog.cloudflare.com/introducing-regional-tiered-cache/</link>
            <pubDate>Thu, 01 Jun 2023 13:00:27 GMT</pubDate>
            <description><![CDATA[ Regional Tiered Cache provides an additional layer of caching for Enterprise customers who have a global traffic footprint and want to serve content faster by avoiding network latency when there is a cache miss in a lower-tier, resulting in an upper-tier fetch in a data center located far away ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/A8lQLOj0zrB1oUjv2YTtX/c7982b28eb35d74286e2ca4e130ae1e7/image5-14.png" />
            
            </figure><p>Today we’re excited to announce an update to our <a href="https://developers.cloudflare.com/cache/about/tiered-cache">Tiered Cache</a> offering: Regional Tiered Cache.</p><p>Tiered Cache allows customers to organize Cloudflare data centers into tiers so that only some “<a href="https://developers.cloudflare.com/cache/about/tiered-cache/#:~:text=upper%2Dtier%20does%20not%20have%20the%20content%2C%20only%20the%20upper%2Dtier%20can%20ask%20the%20origin%20for%20content">upper-tier</a>” data centers can request content from an origin server, and then send content to “<a href="https://developers.cloudflare.com/cache/about/tiered-cache/#:~:text=lower%2Dtier%20data%20centers%20(generally%20the%20ones%20closest%20to%20a%20visitor)">lower-tiers</a>” closer to visitors. Tiered Cache helps content load faster for visitors, makes it cheaper to serve, and <a href="https://developers.cloudflare.com/cache/about/tiered-cache#:~:text=Tiered%20Cache%20concentrates%20connections%20to%20origin%20servers%20so%20they%20come%20from%20a%20small%20number%20of%20data%20centers%20rather%20than%20the%20full%20set%20of%20network%20locations.%20This%20results%20in%20fewer%20open%20connections%20using%20server%20resources.">reduces</a> origin resource consumption.</p><p>Regional Tiered Cache provides an additional layer of caching for Enterprise customers who have a global traffic footprint and want to serve content faster by avoiding <a href="https://www.cloudflare.com/learning/performance/glossary/what-is-latency/">network latency</a> when there is a cache miss in a lower-tier, resulting in an upper-tier fetch in a data center located far away. In our trials, customers who have enabled Regional Tiered Cache have seen a 50-100ms improvement in tail <a href="https://developers.cloudflare.com/cache/about/default-cache-behavior/#cloudflare-cache-responses">cache hit</a> response times from Cloudflare’s CDN.</p>
    <div>
      <h2>What problem does Tiered Cache help solve?</h2>
      <a href="#what-problem-does-tiered-cache-help-solve">
        
      </a>
    </div>
    <p>First, a quick refresher on <a href="https://www.cloudflare.com/learning/cdn/what-is-caching/">caching</a>: a request for content is initiated from a visitor on their phone or computer. This request is generally routed to the closest Cloudflare data center. When the request arrives, we look to see if we have the content cached to respond to that request with. If it’s not in cache (it’s a miss), Cloudflare data centers must contact the <a href="https://www.cloudflare.com/learning/cdn/glossary/origin-server/">origin server</a> to get a new copy of the content.</p><p>Getting content from an origin server suffers from two issues: latency and increased origin egress and load.</p>
    <div>
      <h3>Latency</h3>
      <a href="#latency">
        
      </a>
    </div>
    <p>Origin servers, where content is hosted, can be far away from visitors. This is especially true the more global of an audience a particular piece of content has relative to where the origin is located. This means that content hosted in New York can be served in dramatically different amounts of time for visitors in London, Tokyo, and Cape Town. The farther away from New York a visitor is, the longer they must wait before the content is returned. Serving content from cache helps provide a uniform experience to all of these visitors because the content is served from a data center that’s close.</p>
    <div>
      <h3>Origin load</h3>
      <a href="#origin-load">
        
      </a>
    </div>
    <p>Even when using a <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDN</a>, many different visitors can be interacting with different data centers around the world and each data center, without the content visitors are requesting, will need to reach out to the origin for a copy. This can cost customers money because of egress fees origins charge for sending traffic to Cloudflare, and it places needless load on the origin by opening multiple connections for the same content, just headed to different data centers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5E2xM6zZw1uUJld0wbCn97/b7c2e5723ad36fe15e538aaa89dec94d/download-19.png" />
            
            </figure><p>When Tiered Cache is not enabled, all data centers in Cloudflare’s network can reach out to the origin in the event of a cache miss.</p><p>Performance improvements and origin load reductions are the promise of tiered cache.</p><p>Tiered Caching means that instead of every data center reaching out to the origin when there is a cache miss, the lower-tier data center that is closest to the visitor will reach out to a larger upper-tier data center to see if it has the requested content cached before the upper-tier asks the origin for the content. Organizing Cloudflare’s data centers into tiers means that fewer requests will make it back to the origin for the same content, preserving origin resources, reducing load, and saving the customer money in egress fees.</p>
    <div>
      <h2>What options are there to maximize the benefits of tiered caching?</h2>
      <a href="#what-options-are-there-to-maximize-the-benefits-of-tiered-caching">
        
      </a>
    </div>
    <p>Cloudflare customers are given access to different Tiered Cache topologies based on their plan level. There are currently two predefined Tiered Cache topologies to select from – Smart and Generic Global. If either of those don’t work for a particular customer’s traffic profile, Enterprise customers can also work with us to define a custom topology.</p><p>In <a href="/introducing-smarter-tiered-cache-topology-generation/">2021,</a> we announced that we’d allow all plans to access Smart Tiered Cache. Smart Tiered Cache dynamically finds the single closest data center to a customer’s origin server and chooses that as the upper-tier that all lower-tier data centers reach out to in the event of a cache miss. All other data centers go through that single upper-tier for content and that data center is the only one that can reach out to the origin. This helps to drastically boost cache hit ratios and reduces the connections to the origin. However, this topology can come at the cost of increased latency for visitors that are farther away from that single upper-tier.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4GmpStKUSWMPfYBgk2dAvb/976cee64422a296ed1e776557fe087cc/download--1--13.png" />
            
            </figure><p>When Smart Tiered Cache is enabled, a single upper tier data center can communicate with the origin, helping to conserve origin resources**.**</p><p>Enterprise customers may select additional tiered cache topologies like the Generic Global topology which allows all of Cloudflare’s large data centers on our network (about 40 data centers) to serve as upper-tiers. While this topology may help reduce the long tail latencies for far-away visitors, it does so at the cost of increased connections and load on a customer's origin.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2PMcMuw7DkwI0GxxtLSzYF/616a53624e1392129f2716d40fb2a48a/download--2--11.png" />
            
            </figure><p>When Generic Global Tiered Cache is enabled, lower-tier data centers are mapped to all upper-tier data centers in Cloudflare’s network which can all reach out to the origin in the event of a cache miss. </p><p>To describe the latency problem with Smart Tiered Cache in more detail let’s use an example. Suppose the upper-tier data center is selected to be in New York using Smart Tiered Cache. The traffic profile for the website with the New York upper-tier is relatively global. Visitors are coming from London, Tokyo, and Cape Town. For every cache miss in a lower-tier it will need to reach out to the New York upper-tier for content. This means these requests from Tokyo will need to traverse the Pacific Ocean and most of the continental United States to check the New York upper-tier cache. Then turn around and go all the way back to Tokyo. This is a giant performance hit for visitors outside the US for the sake of improving origin resource load.</p>
    <div>
      <h2>Regional Tiered Cache brings the best of both worlds</h2>
      <a href="#regional-tiered-cache-brings-the-best-of-both-worlds">
        
      </a>
    </div>
    <p>With Regional Tiered Cache we introduce a middle-tier in each region around the world. When a lower-tier fetches on a cache miss it tries the regional-tier first if the upper-tier is in a different region. If the regional-tier does not have the asset then it asks the upper-tier for it. On the response the regional-tier writes to its cache so other lower-tiers in the same region benefit.</p><p>By putting an additional tier in the same region as the lower-tier, there’s an increased chance that the content will be available in the region before heading to a far-away upper-tier. This can drastically improve the performance of assets while still reducing the number of connections that will eventually need to be made to the customer’s origin.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7MIfujQ3l4iMBIQ5ZWdQiU/b8d70abe5ee256c4d95311665b840aca/download--3--7.png" />
            
            </figure><p>When Regional Tiered Cache is enabled, all lower-tier data centers will reach out to a regional tier close to them in the event of a cache miss. If the regional tier doesn’t have the content, the regional tier will then ask an upper-tier out of region for the content. This can help improve latency for Smart and Custom Tiered Cache topologies.</p>
    <div>
      <h2>Who will benefit from regional tiered cache?</h2>
      <a href="#who-will-benefit-from-regional-tiered-cache">
        
      </a>
    </div>
    <p>Regional Tiered Cache helps customers with Smart Tiered Cache or a Custom Tiered Cache topology with upper-tiers in one or two regions. Regional Tiered Cache is not beneficial for customers with many upper-tiers in many regions like Generic Global Tiered Cache .</p>
    <div>
      <h2>How to enable Regional Tiered Cache</h2>
      <a href="#how-to-enable-regional-tiered-cache">
        
      </a>
    </div>
    <p>Enterprise customers can enable Regional Tiered Cache via the Cloudflare Dashboard or the API:</p>
    <div>
      <h3>UI</h3>
      <a href="#ui">
        
      </a>
    </div>
    <ul><li><p>To enable Regional Tiered Cache, simply sign in to your account and select your website</p></li><li><p>Navigate to the Cache Tab of the dashboard, and select the Tiered Cache Section</p></li><li><p>If you have Smart or Custom Tiered Cache Topology Selected, you should have the ability to choose Regional Tiered Cache</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1wj1OVOGbTWsvDy1rHavci/783d587871b8e0dc423e4f23bf18cb02/download--4--7.png" />
            
            </figure>
    <div>
      <h3>API</h3>
      <a href="#api">
        
      </a>
    </div>
    <p>Please see the <a href="https://developers.cloudflare.com/api/operations/zone-cache-settings-get-regional-tiered-cache-setting">documentation</a> for detailed information about how to configure Regional Tiered Cache from the API.</p><p><b>GET</b></p>
            <pre><code>curl --request GET \
 --url https://api.cloudflare.com/client/v4/zones/zone_identifier/cache/regional_tiered_cache \
 --header 'Content-Type: application/json' \
 --header 'X-Auth-Email: '</code></pre>
            <p><b>PATCH</b></p>
            <pre><code>curl --request PATCH \
 --url https://api.cloudflare.com/client/v4/zones/zone_identifier/cache/regional_tiered_cache \
 --header 'Content-Type: application/json' \
 --header 'X-Auth-Email: ' \
 --data '{
 "value": "on"
}'</code></pre>
            
    <div>
      <h2>Try Regional Tiered Cache out today!</h2>
      <a href="#try-regional-tiered-cache-out-today">
        
      </a>
    </div>
    <p>Regional Tiered Cache is the first of many planned improvements to Cloudflare’s Tiered Cache offering which are currently in development. We look forward to hearing what you think about Regional Tiered Cache, and if you’re interested in helping us improve our CDN, <a href="https://www.cloudflare.com/careers/jobs/?department=Engineering">we’re hiring</a>.</p> ]]></content:encoded>
            <category><![CDATA[Tiered Cache]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Latency]]></category>
            <guid isPermaLink="false">6s5rGN6B1pWPNhxDwZ3IRL</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator>Andrew Hauck</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Cache Rules: precision caching at your fingertips]]></title>
            <link>https://blog.cloudflare.com/introducing-cache-rules/</link>
            <pubDate>Tue, 27 Sep 2022 13:00:00 GMT</pubDate>
            <description><![CDATA[ We have spent the last ten years learning how customers use Page Rules to customize their cached content, and it’s clear the time is ripe for evolving rules-based caching on Cloudflare ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Ten years ago, in 2012, we released a product that put “a powerful new set of tools” in the hands of Cloudflare customers, allowing website owners to control how Cloudflare would cache, apply security controls, manipulate headers, implement redirects, and more on any page of their website. This product is called <a href="/introducing-pagerules-fine-grained-feature-co/">Page Rules</a> and since its introduction, it has grown substantially in terms of popularity and functionality.</p><p>Page Rules are a common choice for customers that want to have fine-grained control over how Cloudflare should cache their content. There are more than 3.5 million caching Page Rules currently deployed that help websites customize their content. We have spent the last ten years learning how customers use those rules to cache content, and it’s clear the time is ripe for evolving rules-based caching on Cloudflare. This evolution will allow for greater flexibility in caching different types of content through additional rule configurability, while providing more visibility into when and how different rules interact across Cloudflare’s ecosystem.</p><p>Today, we’ve <a href="/future-of-page-rules">announced</a> that Page Rules will be re-imagined into four product-specific rule sets: Origin Rules, Cache Rules, Configuration Rules, and Redirect Rules.</p><p>In this blog we’re going to discuss <b>Cache Rules</b>, and how we’re applying ten years of product iteration and learning from Page Rules to give you the tools and options to best optimize your cache.</p>
    <div>
      <h3>Activating Page Rules, then and now</h3>
      <a href="#activating-page-rules-then-and-now">
        
      </a>
    </div>
    <p>Adding a Page Rule is very simple: users either make an API call or navigate to the dashboard, enter a full or wildcard URL pattern (e.g. <code>example.com/images/scr1.png</code> or <code>example.com/images/scr*</code>), and tell us which actions to perform when we see that pattern. For example a Page Rule could tell browsers– keep a copy of the response longer via “<a href="https://developers.cloudflare.com/cache/about/edge-browser-cache-ttl/">Browser Cache TTL</a>”, or tell our cache that via “<a href="https://developers.cloudflare.com/cache/about/edge-browser-cache-ttl/">Edge Cache TTL</a>”. Low effort, high impact. All this is accomplished without fighting origin configuration or writing a single line of code.</p><p>Under the hood, a lot is happening to make that rule scale: we turn every rule condition into regexes, matching them against the tens of millions of requests per second across 275+ data centers globally. The compute necessary to process and apply new values on the fly across the globe is immense and corresponds directly to the number of rules we are able to offer to users. By moving cache actions from Page Rules to Cache Rules we can allow for users to not only set more rules, but also to trigger these rules more precisely.</p>
    <div>
      <h3>More than a URL</h3>
      <a href="#more-than-a-url">
        
      </a>
    </div>
    <p>Users of Page Rules are limited to specific URLs or URL patterns to define how browsers or Cloudflare cache their websites files. Cache Rules allows users to set caching behavior on additional criteria, such as the HTTP request headers or the requested file type. Users can continue to match on the requested URL also, as used in our Page Rules example earlier. With Cache Rules, users can now define this behavior on one or more <a href="https://developers.cloudflare.com/cache/about/cache-rules/">fields</a> available.</p><p>For example, if a user wanted to specify cache behavior for all <code>image/png</code> content-types, it’s now as simple as pushing a few buttons in the UI or writing a small expression in the API. Cache Rules give users precise control over when and how Cloudflare and browsers cache their content. Cache Rules allow for rules to be triggered on request header values that can be simply defined like</p><p><code>any(http.request.headers["content-type"][*] == "image/png")</code></p><p>Which triggers the Cache Rule to be applied to all <code>image/png</code> media types. Additionally, users may also leverage other request headers like cookie values, user-agents, or hostnames.</p><p>As a plus, these matching criteria can be stacked and configured with operators like <code>AND</code> and <code>OR</code>, providing additional simplicity in building complex rules from many discrete blocks, e.g. if you would like to target both <code>image/png</code> AND <code>image/jpeg</code>.</p><p>For the full list of fields available conditionals you can apply Cache Rules to, please refer to the <a href="https://developers.cloudflare.com/cache/about/cache-rules/">Cache Rules documentation</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LQO30zIpO4qewcrGtY9Gu/0d472c4b0a4f76513613c1e8b1c9e47e/image1-59.png" />
            
            </figure>
    <div>
      <h3>Visibility into how and when Rules are applied</h3>
      <a href="#visibility-into-how-and-when-rules-are-applied">
        
      </a>
    </div>
    <p>Our current offerings of Page Rules, Workers, and Transform Rules can all manipulate caching functionality for our users’ content. Often, there is some trial and error required to make sure that the confluence of several rules and/or Workers are behaving in an expected manner.</p><p>As part of upgrading Page Rules we have separated it into four new products:</p><ol><li><p>Origin Rules</p></li><li><p>Cache Rules</p></li><li><p>Configuration Rules</p></li><li><p>Redirect Rules</p></li></ol><p>This gives users a better understanding into how and when different parts of the Cloudflare stack are activated, reducing the spin-up and debug time. We will also be providing additional visibility in the dashboard for when rules are activated as they go through Cloudflare. As a sneak peek please see:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6f1aHsgVHcPsfCsLvqyzVH/91f25d4d2e9e3881b736bfac12855bdc/Screenshot-2022-09-27-at-13.03.15.png" />
            
            </figure><p>Our users may take advantage of this strict precedence by chaining the results of one product into another. For example, the output of URL rewrites in Transform Rules will feed into the actions of Cache Rules, and the output of Cache Rules will feed into IP Access Rules, and so on.</p><p>In the future, we plan to increase this visibility further to allow for inputs and outputs across the rules products to be observed so that the modifications made on our network can be observed before the rule is even deployed.</p>
    <div>
      <h3>Cache Rules. What are they? Are they improved? Let’s find out!</h3>
      <a href="#cache-rules-what-are-they-are-they-improved-lets-find-out">
        
      </a>
    </div>
    <p>To start, Cache Rules will have all the caching functionality currently available in Page Rules. Users will be able to:</p><ul><li><p>Tell Cloudflare to cache an asset or not,</p></li><li><p>Alter how long Cloudflare should cache an asset,</p></li><li><p>Alter how long a browser should cache an asset,</p></li><li><p>Define a custom cache key for an asset,</p></li><li><p>Configure how Cloudflare serves stale, revalidates, or otherwise uses header values to direct cache freshness and content continuity,</p></li></ul><p>And so much more.</p><p>Cache Rules are intuitive and work similarly to our other <a href="https://developers.cloudflare.com/ruleset-engine/">ruleset engine</a>-based products announced today: API or UI conditionals for URL or request headers are evaluated, and if matching, Cloudflare and browser caching options are configured on behalf of the user. For all the different options available, see our Cache Rules <a href="https://developers.cloudflare.com/cache/about/cache-rules/">documentation</a>.</p><p>Under the hood, Cache Rules apply targeted rule applications so that additional rules can be supported per user and across the whole engine. What this means for our users is that by consuming less CPU for rule evaluations, we’re able to support more rules per user. For specifics on how many additional Cache Rules you’ll be able to use, please see the <a href="/future-of-page-rules">Future of Rules Blog</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5eNSfTxWDVu2FsRc8JKyIZ/f2a109d9a6b63eebfaa9dcd4f9160b1d/image2-49.png" />
            
            </figure>
    <div>
      <h3>How can you use Cache Rules today?</h3>
      <a href="#how-can-you-use-cache-rules-today">
        
      </a>
    </div>
    <p><b>Cache Rules</b> are available today in beta and can be configured via the <a href="https://developers.cloudflare.com/cache/about/cache-rules/#create-cache-rules-via-api">API</a>, Terraform, or UI in the Caching tab of the dashboard. We welcome you to try the functionality and provide us feedback for how they are working or what additional features you’d like to see via community posts, or however else you generally get our attention ?.</p><p>If you have Page Rules implemented for caching on the same path, Cache Rules will take precedence by design. For our more patient users, we plan on releasing a one-click migration tool for Page Rules in the near future.</p>
    <div>
      <h3>What’s in store for the future of Cache Rules?</h3>
      <a href="#whats-in-store-for-the-future-of-cache-rules">
        
      </a>
    </div>
    <p>In addition to granular control and increased visibility, the new rules products also opens the door to more complex features that can recommend rules to help customers achieve better cache hit ratios and reduce their egress costs, adding additional caching actions and visibility, so you can see precisely how Cache Rules will alter headers that Cloudflare uses to cache content, and allowing customers to run experiments with different rule configurations and see the outcome firsthand. These possibilities represent the tip of the iceberg for the next iteration of how customers will use rules on Cloudflare.</p>
    <div>
      <h3>Try it out!</h3>
      <a href="#try-it-out">
        
      </a>
    </div>
    <p>We look forward to you trying Cache Rules and providing feedback on what you’d like to see us build next.</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[CDN]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Cache Rules]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">5F0VFOCMwG7EXVL6kqOXuK</guid>
            <dc:creator>Alex Krivit</dc:creator>
        </item>
        <item>
            <title><![CDATA[Crawler Hints supports Microsoft’s IndexNow in helping users find new content]]></title>
            <link>https://blog.cloudflare.com/crawler-hints-supports-microsofts-indexnow-in-helping-users-find-new-content/</link>
            <pubDate>Fri, 12 Aug 2022 16:30:20 GMT</pubDate>
            <description><![CDATA[ Cloudflare is uniquely positioned to help give crawlers hints about when they should recrawl, if new content has been added, or if content on a site has recently changed ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/h93ft6NJSg9cczGxRWGu9/eba65d160f1d0701c350a6bc92a21acb/image2-9.png" />
            
            </figure><p>The web is constantly changing. Whether it’s news or updates to your social feed, it’s a constant flow of information. As a user, that’s great. But have you ever stopped to think how search engines deal with all the change?</p><p>It turns out, they “index” the web on a regular basis — sending bots out, to constantly crawl webpages, looking for changes. Today, bot traffic accounts for about <a href="https://radar.cloudflare.com/?date_filter=last_30_days">30% of total traffic</a> on the Internet, and given how foundational search is to using the Internet, it should come as no surprise that search engine bots make up a large proportion of that what might come as a surprise is how inefficient the model is, though: we estimate that over <a href="/crawler-hints-how-cloudflare-is-reducing-the-environmental-impact-of-web-searches/">50% of crawler traffic is wasted effort</a>.</p><p>This has a huge impact. There’s all the additional capacity that owners of websites need to bake into their site to absorb the bots crawling all over it. There’s the transmission of the data. There’s the CPU cost of running the bots. And when you’re running at the scale of the Internet, all of this has a pretty big environmental footprint.</p><p>Part of the problem, though, is nobody had really stopped to ask: maybe there’s a better way?</p><p>Right now, the model for indexing websites is the same as it has been since the 1990s: a “pull” model, where the search engine sends a crawler out to a website after a predetermined amount of time. During Impact Week last year, we asked: what about flipping the model on its head? What about moving to a push model, where a website could simply ping a search engine to let it know an update had been made?</p><p>There are a heap of advantages to such a model. The website wins: it’s not dealing with unnecessary crawls. It also makes sure that as soon as there’s an update to its content, it’s reflected in the search engine — it doesn’t need to wait for the next crawl. The website owner wins because they don't need to manage distinct search engine crawl submissions. The search engine wins, too: it saves money on crawl costs, and it can make sure it gets the latest content.</p><p>Of course, this needs work to be done on both sides of the equation. The websites need a mechanism to alert the search engines; and the search engines need a mechanism to receive the alert, so they know when to do the crawl.</p>
    <div>
      <h3>Crawler Hints — Cloudflare’s Solution for Websites</h3>
      <a href="#crawler-hints-cloudflares-solution-for-websites">
        
      </a>
    </div>
    <p>Solving this problem is why we <a href="/crawler-hints-how-cloudflare-is-reducing-the-environmental-impact-of-web-searches/">launched Crawler Hints</a>. Cloudflare sits in a unique position on the Internet — we’re serving on average 36 million HTTP requests per second. That represents <i>a lot of websites</i>. It also means we’re uniquely positioned to help solve this problem:  to help give crawlers hints about when they should recrawl if new content has been added or if content on a site has recently changed.</p><p>With Crawler Hints, we send signals to web indexers based on cache data and origin status codes to help them understand when content has likely changed or been added to a site. The aim is to increase the number of relevant crawls as well as drastically reduce the number of crawls that don’t find fresh content, saving bandwidth and compute for both indexers and sites alike, and improving the experience of using the search engines.</p><p>But, of course, that’s just half the equation.</p>
    <div>
      <h3>IndexNow Protocol — the Search Engine Moves from Pull to Push</h3>
      <a href="#indexnow-protocol-the-search-engine-moves-from-pull-to-push">
        
      </a>
    </div>
    <p>Websites alerting the search engine about changes is useless if the search engines aren’t listening — and they simply continue to crawl the way they always have. Of course, search engines are incredibly complicated, and changing the way they operate is no easy task.</p><p>The IndexNow Protocol is a standard developed by Microsoft, Seznam.cz and Yandex, and it represents a major shift in the way search engines operate. Using IndexNow, search engines have a mechanism by which they can receive signals from Crawler Hints. Once they have that signal, they can shift their crawlers from a pull model to a push model.</p><p>In a recent update, <a href="https://blogs.bing.com/webmaster/august-2022/IndexNow-adoption-gains-momentum">Microsoft has announced</a> that millions of websites are now using IndexNow to signal to search engine crawlers when their content needs to be crawled and IndexNow was used to <b>index/crawl about 7% of all new URLs</b> <b>clicked</b> when someone is selecting from web search results.</p><p>On the Cloudflare side, since the release of Crawler Hints in October 2021, Crawler Hints has processed about <b>six-hundred-billion</b> signals to IndexNow.</p><p>That’s a lot of saved crawls.</p>
    <div>
      <h3>How to enable Crawler Hints</h3>
      <a href="#how-to-enable-crawler-hints">
        
      </a>
    </div>
    <p>By enabling Crawler Hints on your website, with the simple click of a button, Cloudflare will take care of signaling to these search engines when your content has changed via the <a href="https://www.indexnow.org/">IndexNow</a> API. You don’t need to do anything else!</p><p>Crawler Hints is free to use and available to all Cloudflare customers. If you’d like to see how Crawler Hints can benefit how your website is indexed by the world's biggest search engines, please feel free to opt-into the service by:</p><ol><li><p>Sign in to your Cloudflare Account.</p></li><li><p>In the dashboard, navigate to the Cache tab.</p></li><li><p>Click on the Configuration section.</p></li><li><p>Locate the Crawler Hints and enable.</p></li></ol>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6gbqdPUtYZlLMw8aVmoygy/3b782370e5d898dd5606088c345f7d33/image1-15.png" />
            
            </figure><p>Upon enabling Crawler Hints, Cloudflare will share when content on your site has changed and needs to be re-crawled with search engines using the IndexNow protocol (<a href="/from-0-to-20-billion-how-we-built-crawler-hints/">this blog</a> can help if you’re interested in finding out more about how the mechanism works).</p>
    <div>
      <h3>What’s Next?</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>Going forward, because the benefits are so substantial for site owners, search operators, and the environment, we plan to start defaulting Crawler Hints on for all our customers. We’re also hopeful that Google, the world’s largest search engine and most wasteful user of Internet resources, will adopt IndexNow or a similar standard and lower the burden of search crawling on the planet.</p><p>When we think of helping to build a better Internet, this is exactly what comes to mind: creating and supporting standards that make it operate better, greener, faster. We’re really excited about the work to date, and will continue to work to improve the signaling to ensure the most valuable information is being sent to the search engines in a timely manner. This includes incorporating additional signals such as etags, last-modified headers, and content hash differences. Adding these signals will help further inform crawlers when they should reindex sites, and how often they need to return to a particular site to check if it’s been changed. This is only the beginning. We will continue testing more signals and working with industry partners so that we can help crawlers run efficiently with these hints.</p><p>And finally: if you’re on Cloudflare, and you’d like to be part of this revolution in how search engines operate on the web (it’s free!), simply follow the instructions in the section above.</p> ]]></content:encoded>
            <category><![CDATA[Crawler Hints]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[SEO]]></category>
            <guid isPermaLink="false">5LL6jyHzqmppNptbCOrWuQ</guid>
            <dc:creator>Alex Krivit</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing Smart Edge Revalidation]]></title>
            <link>https://blog.cloudflare.com/introducing-smart-edge-revalidation/</link>
            <pubDate>Wed, 28 Jul 2021 12:59:17 GMT</pubDate>
            <description><![CDATA[ When both Last-Modified and Etag headers are absent from the origin response, Smart Edge Revalidation will use the time the object was cached on Cloudflare as the Last-Modified header value. When  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today we’re excited to announce Smart Edge Revalidation. It was designed to ensure that compute resources are synchronized efficiently between our edge and a browser. Right now, as many as 30% of objects cached on Cloudflare’s edge do not have the HTTP response headers required for revalidation. This can result in unnecessary origin calls. Smart Edge Revalidation fixes this: it does the work to ensure that these headers are present, even when an origin doesn’t send them to us. The advantage of this? There’s less wasted bandwidth and compute for objects that do not need to be redownloaded. And there are faster browser page loads for users.</p>
    <div>
      <h2>So What Is Revalidation?</h2>
      <a href="#so-what-is-revalidation">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/gTlB9tlXkMhFpf88xVu9O/6fd36a3a9baa63e2c20b9ea49d54bd03/Cache-Hit--Miss.png" />
            
            </figure><p>Revalidation is one part of a longer story about efficiently serving objects that live on an origin server from an intermediary cache. Visitors to a website want it to be fast. One foundational way to make sure that a website is fast for visitors is to serve objects from cache. In this way, requests and responses do not need to transit unnecessary parts of the Internet back to an origin and, instead, can be served from a data center that is closer to the visitor. As such, website operators generally only want to serve content from an origin when content has changed. So how do objects stay in cache for as long as necessary?</p><p>One way to do that is with HTTP response headers.</p><p>When Cloudflare gets a response from an origin, included in that response are a number of headers. You can see these headers by opening any webpage, inspecting the page, going to the network tab, and clicking any file. In the response headers section there will generally be a header known as “<code>Cache-Control</code>.” This header is a way for origins to answer caching intermediaries’ questions like: is this object eligible for cache? How long should this object be in cache? And what should the caching intermediary do after that time expires?</p><div></div><p>How long something should be in cache can be specified through the <code>max-age</code> or <code>s-maxage</code> directives. These directives specify a TTL or time-to-live for the object in seconds. Once the object has been in cache for the requisite TTL, the clock hits 0 (zero) and it is marked as expired. Cache can no longer safely serve expired content to requests without figuring out if the object has changed on the origin or if it is the same.</p><p>If it has changed, it must be redownloaded from the origin. If it hasn’t changed, then it can be marked as fresh and continue to be served. This check, again, is known as revalidation.</p><p>We’re excited that Smart Edge Revalidation extends the efficiency of revalidation to everyone, regardless of an origin sending the necessary response headers</p>
    <div>
      <h2>How is Revalidation Accomplished?</h2>
      <a href="#how-is-revalidation-accomplished">
        
      </a>
    </div>
    <p>Two additional headers, <a href="https://datatracker.ietf.org/doc/html/rfc7232#section-2.2"><code>Last-Modified</code></a> and <a href="https://datatracker.ietf.org/doc/html/rfc7232#section-2.3"><code>ETag</code></a>, are set by an origin in order to distinguish different versions of the same URL/object across modifications. After the object expires and the revalidation check occurs, if the <code>ETag</code> value hasn’t changed or a more recent <code>Last-Modified</code> timestamp isn’t present, the object is marked “revalidated” and the expired object can continue to be served from cache. If there has been a change as indicated by the <code>ETag</code> value or <code>Last-Modified</code> timestamp, then the new object is downloaded and the old object is removed from cache.</p><p>Revalidation checks occur when a browser sends a request to a cache server using <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since"><code>If-Modified-Since</code></a> or <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match"><code>If-None-Match</code></a> headers. These <i>request headers</i> are questions sent from the browser cache about when an object has last changed that can be answered via the <code>ETag</code> or <code>Last-Modified</code> <i>response headers</i> on the cache server. For example, if the browser sends a request to a cache server with <code>If-Modified-Since: Tue, 8 Nov 2021 07:28:00 GMT</code> the cache server must look at the object being asked about and if it has not changed since November 8 at 7:28 AM, it will respond with a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304">304 status code</a> indicating it’s unchanged. If the object has changed, the cache server will respond with the new object.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5prstYJc5fXhuiLi8ulIxg/78a8cbd21546b33b2afea42bf3ea9826/Cache-Response-Header.png" />
            
            </figure><p>Sending a 304 status code that indicates an object can be reused is much more efficient than sending the entire object. It’s like if you ran a news website that updated every 24 hours. Once the content is updated for the day, you wouldn’t want to keep redownloading the same unchanged content from the origin and instead, you would prefer to make sure that the day’s content was just reused by sending a lightweight signal to that effect, until the site changes the next day.</p><p>The problem with this system of browser questions and revalidation responses is that sometimes origins don’t set <code>ETag</code> or <code>Last-Modified</code> headers, or they aren’t configured by the website’s admin, making revalidation impossible. This means that every time an object expires, it must be redownloaded regardless of if there has been a change or not, because we have to assume that the asset has been updated, or else risk serving stale content.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1RvLJ1Px9qitcuzYQmdlUO/86c73964fd7f8d18ed2697ce3b4fc350/Origin-Response-Header.png" />
            
            </figure><p>This is an incredible waste of resources which costs hundreds of GB/sec of needless bandwidth between the edge and the visitor. Meaning browsers are downloading hundreds of GB/sec of content they <i>may already have</i>. If our baseline of revalidation is around 10% of all traffic and in initial tests, Smart Edge Revalidation increased revalidation just under 50%, this means that without a user needing to configure <b>anything</b>, we can increase total revalidations by around 5%!</p><p>Such a large reduction in bandwidth use also comes with potential environmental benefits. Based on Cloudflare's carbon emissions per byte, the needless bandwidth being used could amount to 2000+ metric tons CO2e/year, the equivalent of the <a href="https://www.epa.gov/energy/greenhouse-gas-equivalencies-calculator">CO2 emissions</a> from more than 400 cars in a year.</p><p>Revalidation also comes with a performance improvement because it usually means a browser is downloading less than 1KB of data to check if the asset has changed or not, while pulling the full asset can be 100sKB. This can improve performance and reduce the bandwidth between the visitor and our edge.</p>
    <div>
      <h2>How Smart Edge Revalidation Works</h2>
      <a href="#how-smart-edge-revalidation-works">
        
      </a>
    </div>
    <p>When both <code>Last-Modified</code> and <code>Etag</code> headers are <i>absent</i> from the origin server response, Smart Edge Revalidation will use the time the object was cached on Cloudflare’s edge as the <code>Last-Modified</code> header value. When a browser sends a revalidation request to Cloudflare using <code>If-Modified-Since</code> or <code>If-None-Match</code>, our edge can answer those revalidation questions using the <code>Last-Modified</code> header generated from Smart Edge Revalidation. In this way, our edge can ensure efficient revalidation even if the headers are not sent from the origin.</p><p>Smart Edge Revalidation will be enabled automatically for all Cloudflare customers over the coming weeks. If this behavior is undesired, you can always ensure that Smart Edge Revalidation is not activated by <a href="https://web.dev/http-cache/#response-headers">confirming your origin</a> is sending <code>ETag</code> or <code>Last-Modified</code> headers when you want to indicate changed content. Additionally, you could have your origin direct your desired revalidation behavior by making sure it sets appropriate <a href="https://support.cloudflare.com/hc/en-us/articles/115003206852-Understanding-Origin-Cache-Control">cache-control headers</a>.</p><p>Smart Edge Revalidation is a win for everyone: visitors will get more content faster from cache, website owners can serve and revalidate additional content from Cloudflare efficiently, and the Internet will get a bit greener and more efficient.</p><p>Smart Edge Revalidation is the latest announcement to join the list of ways we're making our network more sustainable to help build a greener Internet — check out posts from earlier this week to learn about our <a href="/cloudflare-committed-to-building-a-greener-internet/">climate commitments</a>, <a href="/announcing-green-compute/">Green Compute with Workers</a>, <a href="https://assets.ctfassets.net/slt3lc6tev37/2YzIeTtzSbyKkM4GsryP5S/62ce0dff98e92a142281a0b462ce4408/Cloudflare_Emissions_Inventory_-_2020.pdf">Carbon Impact Report</a>, <a href="/green-hosting-with-cloudflare-pages/">Pages x Green Web Foundation partnership</a>, and <a href="/crawler-hints-how-cloudflare-is-reducing-the-environmental-impact-of-web-searches/">crawler hints</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/guKMx74ygDjoGcziS5Usf/41e7cf39b57f8c9ba7c7052e2f4fbd62/Green-Cache.png" />
            
            </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Impact Week]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Edge]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">6DXhhWwE8C0xQ3eKp7tthE</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator>Yuchen Wu</dc:creator>
        </item>
        <item>
            <title><![CDATA[CDN-Cache-Control: Precision Control for your CDN(s)]]></title>
            <link>https://blog.cloudflare.com/cdn-cache-control/</link>
            <pubDate>Fri, 21 May 2021 11:00:02 GMT</pubDate>
            <description><![CDATA[ A new set of HTTP response headers provide control over our CDN’s caching decisions. CDN-Cache-Control allows customers to control how our CDN behaves without affecting the behavior of other caches. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today we are thrilled to announce our support of a new set of HTTP response headers that provide surgical control over our CDN’s caching decisions. <a href="https://datatracker.ietf.org/doc/html/draft-cdn-control-header-01">CDN-Cache-Control</a> allows customers to directly control how our <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDN</a> behaves without affecting the behavior of downstream or upstream caches.</p><p>You might be thinking that this sounds a lot like the <a href="https://support.cloudflare.com/hc/en-us/articles/115003206852-Understanding-Origin-Cache-Control">Cache-Control</a> header we all know and love. And it’s very similar! CDN-Cache-Control has exactly the same directives as the Cache-Control header. The problem CDN-Cache-Control sets out to solve is that with Cache-Control, some directives are targeted at specific classes of caches (like <code>s-maxage</code> for shared caches), while other directives are not targeted at controlling any specific classes of intermediary caches (think <code>stale-while-revalidate</code>). As these non-specific directives are returned to downstream caches, they’re often not applied uniformly. This problem is amplified as the number of intermediary caches grows between an origin and the client.</p><p>For example, a website may deploy a caching layer on the origin server itself, there might be a cache on the origin’s network, the site might use one or more CDNs to cache content distributed throughout the Internet, and the visitor’s browser might cache content as well. As the response returns from the origin, each of these layers must interpret the set Cache-Control directives. These layers, however, are not guaranteed to interpret Cache-Control in the same way, which can cause unexpected behavior and confusion.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/767XtpC9Rywutdgs1h0SC6/844b566957308086e8610fc2ce2bd0ac/image2-6.png" />
            
            </figure><p>We set out to <a href="https://www.cloudflare.com/learning/cdn/common-cdn-issues/">solve these problems</a> and have been working with industry peers who also run large CDNs to create an <a href="https://datatracker.ietf.org/doc/html/draft-cdn-control-header-01">industry standard solution</a> through the Internet Engineering Task Force. CDN-Cache-Control is aimed at providing directives to manage how specific CDNs behave when caching objects.</p>
    <div>
      <h2>Introducing CDN-Cache-Control</h2>
      <a href="#introducing-cdn-cache-control">
        
      </a>
    </div>
    <p>CDN-Cache-Control is a response header field set on the origin to control the behavior of CDN caches separately from other intermediaries that might handle a response. This feature can be used by setting the CDN-Cache-Control and/or <b>Cloudflare-CDN-Cache-Control</b> response header. Both of these new headers support the same directives currently supported by Cache-Control and also have the same semantics and directive precedence. In other words, if you were to copy and paste a Cache-Control value and insert it into either of these new headers, the same caching behavior should be observed.</p>
    <div>
      <h2>Header precedence; or, which header should I use when?</h2>
      <a href="#header-precedence-or-which-header-should-i-use-when">
        
      </a>
    </div>
    <p>When introducing a set of new cache response headers, a question at the forefront of the cache-conscious mind is how will these directives work when combined with each other or other Cache-Control directives? There are several options depending on how these headers are used. An origin can:</p><ol><li><p>Return the CDN-Cache-Control response header which Cloudflare will evaluate to make caching decisions. Cache-Control, if also returned by the origin, will be proxied as is (more on this later) and will not affect caching decisions made by Cloudflare. In addition, CDN-Cache-Control will also be proxied downstream in case there are other CDNs between Cloudflare and the browser.</p></li><li><p>Return the Cloudflare-CDN-Cache-Control response header. This results in the same behavior as the origin returning CDN-Cache-Control except we will NOT proxy Cloudflare-CDN-Cache-Control downstream because it’s a header only used to control Cloudflare. This is beneficial if you want only Cloudflare to have a different caching behavior while having all downstream servers rely on Cache-Control, or you simply don’t want Cloudflare to proxy the CDN-Cache-Control header downstream.</p></li><li><p>Return both Cloudflare-CDN-Cache-Control and CDN-Cache-Control response headers. In this case, Cloudflare will only look at Cloudflare-CDN-Cache-Control when making caching decisions because it is the most specific version of CDN-Cache-Control and will proxy CDN-Cache-Control downstream. Only forwarding CDN-Cache-Control in this situation is beneficial if you want Cloudflare to have a different caching behavior than other CDNs downstream.</p></li></ol><p>For example, a response leaves the origin server and can hit the following caches on the way to the browser and can be controlled by the following response headers (assuming the other CDNs support CDN-Cache-Control):</p>
<div><table><thead>
  <tr>
    <th><span>Caches </span></th>
    <th><span>Control Headers</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Origin Server Cache</span></td>
    <td><span>Cache-Control </span></td>
  </tr>
  <tr>
    <td><span>Shared Cache on the Origin Network</span></td>
    <td><span>Cache-Control </span></td>
  </tr>
  <tr>
    <td><span>CDN #1</span></td>
    <td><span>CDN-Cache-Control</span></td>
  </tr>
  <tr>
    <td><span>Cloudflare CDN</span></td>
    <td><span>Cloudflare-CDN-Cache-Control/CDN-Cache-Control</span></td>
  </tr>
  <tr>
    <td><span>CDN #N</span></td>
    <td><span>CDN-Cache-Control</span></td>
  </tr>
  <tr>
    <td><span>Browser Cache</span></td>
    <td><span>Cache-Control </span></td>
  </tr>
</tbody></table></div><p>With these headers and directives set, intermediaries know whether it’s safe for something to be cached, how long it should be cached, and what to do once it’s no longer permitted to remain in cache.</p>
    <div>
      <h2>Interaction with other Cloudflare features</h2>
      <a href="#interaction-with-other-cloudflare-features">
        
      </a>
    </div>
    
    <div>
      <h3>Edge Cache TTL Page Rule</h3>
      <a href="#edge-cache-ttl-page-rule">
        
      </a>
    </div>
    <p>Edge Cache TTL is a <a href="https://support.cloudflare.com/hc/en-us/articles/218411427-Understanding-and-Configuring-Cloudflare-Page-Rules-Page-Rules-Tutorial-#h_18YTlvNlZET4Poljeih3TJ">page rule</a> that is meant to override the amount of time an asset is cached on the edge (Cloudflare data centers) and therefore overrides directives in Cloudflare-CDN-Cache-Control/CDN-Cache-Control managing how long an asset is cached on the edge. This page rule can be set in the rules section of the dashboard.</p>
    <div>
      <h3>Browser Cache TTL Page Rule</h3>
      <a href="#browser-cache-ttl-page-rule">
        
      </a>
    </div>
    <p><a href="https://support.cloudflare.com/hc/en-us/articles/200168276-Understanding-Browser-Cache-TTL">Browser Cache TTL</a> is a page rule that is meant to override the amount of time an asset is cached by browsers/servers downstream of Cloudflare. Therefore, Browser Cache TTL will only modify the <b>Cache-Control</b> response header. Cloudflare-CDN-Cache-Control/CDN-Cache-Control response headers will not be modified by this page rule.</p>
    <div>
      <h3>Interaction With Other Origin Response Headers</h3>
      <a href="#interaction-with-other-origin-response-headers">
        
      </a>
    </div>
    <p>The Expires response header returned by the origin, which generally directs a browser on how long before an object should be considered stale, will not affect the caching decision at Cloudflare when Cloudflare-CDN-Cache-Control/CDN-Cache-Control is being used.</p>
    <div>
      <h3>Interaction with Cloudflare Default Cache Values</h3>
      <a href="#interaction-with-cloudflare-default-cache-values">
        
      </a>
    </div>
    <p>In the situation where Cloudflare does not receive Cloudflare-CDN-Cache-Control, CDN-Cache-Control, or Cache-Control values, the general <a href="https://support.cloudflare.com/hc/en-us/articles/200172516#h_51422705-42d0-450d-8eb1-5321dcadb5bc">default values</a> will be used for cacheable assets.</p>
    <div>
      <h2>When should I use CDN-Cache-Control?</h2>
      <a href="#when-should-i-use-cdn-cache-control">
        
      </a>
    </div>
    <p>Caching is one of the most powerful tools available to ensure all possible requests are served from data centers near visitors to improve a website’s performance and limit origin egress. Cache-Control directives are the rules that dictate how caches should behave. These rules dictate how long something should stay in cache and direct the cache on what to do once that content has expired. However, in a setup where there are numerous caching layers between the origin and client, getting the desired control over each hop a response makes back to the client is complicated. This difficulty is exacerbated by unpredictable behavior by intermediary caches proxying or stripping cache control headers sent downstream.</p><p>Let’s walk through a few examples for how to use CDN-Cache-Control:</p>
    <div>
      <h3>Acme Corp</h3>
      <a href="#acme-corp">
        
      </a>
    </div>
    <p>Acme Corp is a user of Cloudflare’s CDN. They want to manage their cached asset’s TTLs separately for origin caches, CDN caches, and browser caches. Previously, Page Rules were required to specify their desired behavior. Now with CDN-Cache-Control, this common scenario can be accomplished solely through the use of origin-set response headers.</p><p><b>Before</b></p><p>Headers:</p><ul><li><p>Cache-Control: max-age=14400, s-maxage=84000</p></li><li><p>Set an Edge Cache TTL Page Rule on Cloudflare for 24400 seconds fixed to the asset’s path</p></li></ul><p>Cache Behavior:</p>
<div><table><thead>
  <tr>
    <th><span>Caches</span></th>
    <th><span>Cache TTL (seconds)</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Origin Server Cache</span></td>
    <td><span>14400</span></td>
  </tr>
  <tr>
    <td><span>Cloudflare Edge</span></td>
    <td><span>24400</span></td>
  </tr>
  <tr>
    <td><span>Other CDNs</span></td>
    <td><span>84000</span></td>
  </tr>
  <tr>
    <td><span>Browser Cache</span></td>
    <td><span>14400</span></td>
  </tr>
</tbody></table></div><p><b>Now (no need for Page Rule configuration, and can set different TTLs on different CDNs)</b></p><p>Headers:</p><ul><li><p>Cache-Control: max-age=14400, s-maxage=84000</p></li><li><p>Cloudflare-CDN-Cache-Control: max-age=24400</p></li><li><p>CDN-Cache-Control: 18000</p></li></ul><p>Cache Behavior:</p>
<div><table><thead>
  <tr>
    <th><span>Caches</span><span> </span></th>
    <th><span>Cache TTL (seconds)</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Origin Server Cache</span></td>
    <td><span>14400</span></td>
  </tr>
  <tr>
    <td><span>Network Shared Cache</span></td>
    <td><span>84000</span></td>
  </tr>
  <tr>
    <td><span>Cloudflare Edge</span></td>
    <td><span>24400</span></td>
  </tr>
  <tr>
    <td><span>Other CDNs</span></td>
    <td><span>18000</span></td>
  </tr>
  <tr>
    <td><span>Browser Cache</span></td>
    <td><span>14400</span></td>
  </tr>
</tbody></table></div>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/748TZ8fC9P7Fpcc7HlDQHS/53fe73aaad00de84a6cd0e7eb87e0bde/image3-7.png" />
            
            </figure>
    <div>
      <h3>ABC Industries</h3>
      <a href="#abc-industries">
        
      </a>
    </div>
    <p>ABC Industries uses multiple CDNs stacked together serially and wants cache-specific control over when to serve stale content in the case of an error or during revalidation. This can more easily be expressed by using the new CDN-Cache-Control headers in combination with Cache-Control headers.</p><p>Previously, if a user wanted to specify when certain intermediaries should serve stale content, this could not be done. It was up to the cache to decide whether or not the directive applied to it and whether it should pass the header downstream. The new headers provide CDN-specific control for when to use stale assets to fulfill requests.</p><p><b>Before</b></p><p>Headers:</p><ul><li><p>Cache-Control: stale-if-error=400</p></li></ul><p>Behavior in response to 5XX Error:</p>
<div><table><thead>
  <tr>
    <th><span>Caches</span></th>
    <th><span>Stale served (seconds) in response to error</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Origin Cache Layer</span></td>
    <td><span>400 (if it assumes the directive applies)</span></td>
  </tr>
  <tr>
    <td><span>Cloudflare Edge</span></td>
    <td><span>400 (we assume the directive applies if we get it from upstream) </span></td>
  </tr>
  <tr>
    <td><span>Unknown CDN/Network caches/Browser Cache</span></td>
    <td><span>0 (if they assume the directives doesn’t apply or they don’t get them from upstream); or 400 (if they do assume it applies)</span></td>
  </tr>
</tbody></table></div><p><b>Now (explicit indication of when directives apply to CDNs)</b></p><p>Headers:</p><ul><li><p>Cache-Control: stale-if-error=400</p></li><li><p>Cloudflare-CDN-Cache-Control: stale-if-error=60</p></li><li><p>CDN-Cache-Control: stale-if-error=200</p></li></ul><p>Behavior in response to 5XX Error:</p>
<div><table><thead>
  <tr>
    <th><span>Caches</span></th>
    <th><span>Stale served (seconds) in response to error</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Origin Cache Layer/Network Cache/Browser Cache</span></td>
    <td><span>400 (if it assumes the directive applies)</span></td>
  </tr>
  <tr>
    <td><span>Cloudflare Edge</span></td>
    <td><span>60</span></td>
  </tr>
  <tr>
    <td><span>Other CDN</span></td>
    <td><span>200</span></td>
  </tr>
</tbody></table></div>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6RDiwoaXQRmDRkSNhIi8NA/def3789cd66097c3140e09ef3b51896e/image4-10.png" />
            
            </figure>
    <div>
      <h2>Try it out!</h2>
      <a href="#try-it-out">
        
      </a>
    </div>
    <p><b>Overall, CDN-Cache-Control allows finer grained control of how Cloudflare manages cache lifetimes and revalidation behavior on a per-asset basis.</b></p><p>If you’re looking for more control over how your CDNs’ cache objects, I encourage you to try these new headers out. And if you’re another CDN reading this, I recommend looking to add support for <a href="https://datatracker.ietf.org/doc/html/draft-cdn-control-header-01">CDN-Cache-Control</a>!</p> ]]></content:encoded>
            <category><![CDATA[CDN]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">4HgNrGAchRxNQH8Zqphswv</guid>
            <dc:creator>Alex Krivit</dc:creator>
            <dc:creator>Zaidoon Abd Al Hadi</dc:creator>
        </item>
        <item>
            <title><![CDATA[Third Time’s the Cache, No More]]></title>
            <link>https://blog.cloudflare.com/third-times-the-cache-no-more/</link>
            <pubDate>Fri, 19 Mar 2021 12:00:00 GMT</pubDate>
            <description><![CDATA[ Up until now, we wouldn’t cache requests with query strings until we saw them three times. We trace that behavior back to 2010, examine why we might have needed it, and show ourselves why we don’t need it anymore. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Caching is a big part of how Cloudflare CDN makes the Internet faster and more reliable. When a visitor to a customer’s website requests an asset, we retrieve it from the customer’s origin server. After that first request, in many cases we <i>cache</i> that asset. Whenever anyone requests it again, we can serve it from one of our data centers close to them, dramatically speeding up load times.</p><p>Did you notice the small caveat? We cache after the <i>first</i> request in <i>many</i> cases, not all. One notable exception since 2010 up until now: requests with <i>query strings</i>. When a request came with a query string (think <a href="https://example.com/image.jpg?width=500">https://example.com/image.jpg?width=500</a>; the <code>?width=500</code> is the query string), we needed to see it a whole <i>three</i> times before we would cache it on our <a href="https://support.cloudflare.com/hc/en-us/articles/200168256-Understand-Cloudflare-Caching-Level">default cache level</a>. Weird!</p><p>This is a short tale of that strange exception, why we thought we needed it, and how, more than ten years later, we showed ourselves that we didn’t.</p>
    <div>
      <h3>Two MISSes too many</h3>
      <a href="#two-misses-too-many">
        
      </a>
    </div>
    <p>To see the exception in action, here’s a command we ran a couple weeks ago. It requests an image hosted on <code>example.com</code> five times and prints each response’s <a href="https://support.cloudflare.com/hc/en-us/articles/200172516-Understanding-Cloudflare-s-CDN#h_bd959d6a-39c0-4786-9bcd-6e6504dcdb97">CF-Cache-Status header</a>. That header tells us what the cache did while serving the request.</p>
            <pre><code>❯ for i in {1..5}; do curl -svo /dev/null example.com/image.jpg 2&gt;&amp;1 | grep -e 'CF-Cache-Status'; sleep 3; done
&lt; CF-Cache-Status: MISS
&lt; CF-Cache-Status: HIT
&lt; CF-Cache-Status: HIT
&lt; CF-Cache-Status: HIT
&lt; CF-Cache-Status: HIT</code></pre>
            <p>The MISS means that we couldn’t find the asset in the cache and had to retrieve it from the origin server. On the HITs, we served the asset from cache.</p><p>Now, just by adding a query string to the same request (<code>?query=val</code>):</p>
            <pre><code>❯ for i in {1..5}; do curl -svo /dev/null example.com/image.jpg\?query\=val 2&gt;&amp;1 | grep -e 'CF-Cache-Status'; sleep 3; done
&lt; CF-Cache-Status: MISS
&lt; CF-Cache-Status: MISS
&lt; CF-Cache-Status: MISS
&lt; CF-Cache-Status: HIT
&lt; CF-Cache-Status: HIT</code></pre>
            <p>There they are - three MISSes, meaning two extra trips to the customer origin!</p><p>We traced this surprising behavior back to a git commit from Cloudflare’s earliest days in 2010. Since then, it has spawned chat threads, customer escalations, and even an internal Solutions Engineering blog post that christened it the “third time’s the charm” quirk.</p><p>It would be much less confusing if we could make the query string behavior align with the others, but why was the quirk here to begin with?</p>
    <div>
      <h3>Unpopular queries</h3>
      <a href="#unpopular-queries">
        
      </a>
    </div>
    <p>From an engineering perspective, forcing three MISSes for query strings can make sense as a way to protect ourselves from unnecessary disk writes.</p><p>That’s because for many requests with query strings in the URL, we may never see that URL requested again.</p><ol><li><p>Some query strings simply pass along data to the origin server that may not actually result in a different response from the base URL, for example, a visitor’s browser metadata. We end up caching the same response behind many different, potentially unique, cache keys.</p></li><li><p>Some query strings are <i>intended</i> to bypass caches. These “cache busting” requests append randomized query strings in order to force pulling from the origin, a strategy that some <a href="https://support.google.com/campaignmanager/answer/2837435?hl=en#zippy=%2Chow-does-cache-busting-work">ad managers use to count impressions</a>.</p></li></ol><p>Unpopular requests are not a new problem for us. Previously, <a href="/why-we-started-putting-unpopular-assets-in-memory/">we wrote about how we use an in-memory transient cache</a> to store requests we only ever see once (dubbed “one-hit-wonders”) so that they are never written to disk. This transient cache, enabled for just a subset of traffic, reduces our disk writes by 20-25%.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/57yHAVDQQJWmKXvIkZirLm/24ee2c3198f5af8b54a07c8e545ec9f8/image2-15.png" />
            
            </figure><p>Was this behavior from 2010 giving us similar benefits? Since then, our network has grown from 10,000 Internet properties to 25 million. It was time to re-evaluate. Just how much would our disk writes increase if we cached on the first request? How much better would cache hit ratios be?</p>
    <div>
      <h3>Hypotheses: querying the cache</h3>
      <a href="#hypotheses-querying-the-cache">
        
      </a>
    </div>
    <p>Good news: our metrics showed only around 3.5% of requests use the default cache level with query strings. Thus, we shouldn’t expect more than a few percentage points difference in disk writes. Less good: <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cache-hit-ratio/">cache hit rate</a> shouldn’t increase much either.</p><p>On the other hand, we also found that a significant portion of these requests are images, which could potentially take up lots of disk space and hike up cache eviction rates. Enough napkin math - we needed to start assessing real world data.</p>
    <div>
      <h3>A/B testing: caching the queries</h3>
      <a href="#a-b-testing-caching-the-queries">
        
      </a>
    </div>
    <p>We were able to validate our hypotheses using an <a href="https://en.wikipedia.org/wiki/A/B_testing">A/B test</a>, where half the machines in a data center use the old behavior and half do not. This enabled us to control for Internet traffic fluctuations over time and get more precise impact numbers.</p><p>Other considerations: we limited the test to one data center handling a small slice of our traffic to minimize the impact of any negative side effects. We also disabled transient cache, which would nullify some of the I/O costs we expected to observe. By turning transient cache off for the experiment, we should see the upper bound of the disk write increase.</p><p>We ran this test for a couple days and, as hypothesized, found a minor but acceptable increase in disk writes per request to the tune of 2.5%.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2QFiZGM6WpUd9OYZ135xLb/1a57482bbecd6e08f93d4102b7b0359a/image3-17.png" />
            
            </figure><p>What’s more, we saw a modest hit rate increase of around +3% on average for our Enterprise customers. More hits meant fewer trips to origin servers and thus bandwidth savings for customers: in this case, a -5% decrease in total bytes served from origin.</p><p>Note that we saw hit rate increases for certain customers across <i>all</i> plan types. Those with the biggest boost had a variety of query strings across different visitor populations (e.g. appending query strings such as <code>?resize=100px:*&amp;output-quality=60</code> <a href="https://developers.cloudflare.com/images/resizing-with-workers">to optimize serving images for different screen sizes</a>). A few additional HITs for many different, but still popular, cache keys really added up.</p>
    <div>
      <h3>Revisiting old assumptions</h3>
      <a href="#revisiting-old-assumptions">
        
      </a>
    </div>
    <p>What the aggregate hit rate increase implied was that for a significant portion of customers, our old query string behavior was too defensive. We were overestimating the proportion of query string requests that were one-hit-wonders.</p><p>Given that these requests are a relatively small percentage of total traffic, we didn’t expect to see massive hit rate improvements. In fact, if the assumptions about many query string requests being one-hit-wonders were correct, we should hardly be seeing any difference at all. (One-hit-wonders are actually “one MISS wonders” in the context of hit rate.) Instead, we saw hit rate increases proportional to the affected traffic percentage. This, along with the minor I/O cost increases, signaled that the benefits of removing the behavior would outweigh the benefits of keeping it.</p><p>Using a data-driven approach, we determined our caution around caching query string requests wasn’t nearly as effective at preventing disk writes of unpopular requests compared to our newer efforts, such as transient cache. It was a good reminder for us to re-examine past assumptions from time-to-time and see if they still held.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/29s2kKkqUOMWDmlFHY5qp8/60a7d113cde89a6e197d4536bd911e7b/image4-15.png" />
            
            </figure><p>Post-experiment, we gradually rolled out the change to verify that our cost expectations were met. At this time, we’re happy to report that we’ve left the “third time’s the charm” quirk behind for the history books. Long live “cache at first sight.”</p> ]]></content:encoded>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Performance]]></category>
            <guid isPermaLink="false">5cQYvM7O47Nb1C1zoxwG4Q</guid>
            <dc:creator>Edward Wang</dc:creator>
        </item>
        <item>
            <title><![CDATA[Automatic Platform Optimization post-launch report]]></title>
            <link>https://blog.cloudflare.com/apo-post-launch-report/</link>
            <pubDate>Tue, 16 Mar 2021 12:00:00 GMT</pubDate>
            <description><![CDATA[ We explored almost 200 websites with the activated Automatic Platform Optimization feature in Chrome User Experience Report data. Automatic Platform Optimization consistently demonstrated better aggregate performance among sites we analyzed in TTFB, First Paint, FCP, and LCP metrics. ]]></description>
            <content:encoded><![CDATA[ <p>Last year during <a href="/automatic-platform-optimizations-starting-with-wordpress/">Birthday Week</a>, we announced Automatic Platform Optimization for WordPress (APO): smart HTML caching for WordPress sites using Cloudflare. Initial testing across various WordPress sites demonstrated significant improvements in performance metrics like Time to First Byte (TTFB), First Contentful Paint (FCP), and Speed Index. We wanted to measure how APO impacted web performance for our customers since the launch.</p><p>In the blog post, we answer the following questions:</p><ul><li><p>How fast is Automatic Platform Optimization? Can you demonstrate it with data?</p></li></ul><p>We will show real-world improvements for several performance metrics.</p><ul><li><p>Is Automatic Platform Optimization flexible enough to integrate smoothly with my WordPress site?</p></li></ul><p>We have added and improved lots of features since the initial launch.</p><ul><li><p>Will Automatic Platform Optimization work when used with other plugins?</p></li></ul><p>We will cover the most common use cases and explain how Automatic Platform Optimization could be fined-tuned.</p>
    <div>
      <h2>Measuring performance with WebPageTest</h2>
      <a href="#measuring-performance-with-webpagetest">
        
      </a>
    </div>
    <p>We use WebPageTest as a go-to tool for <a href="/new-speed-page/">synthetic testing at Cloudflare</a>. It measures web performance metrics in real browsers, is highly programmable, and could scale to test millions of sites per day. Among the benefits of synthetic testing are easy to produce results and their relatively high reproducibility.</p><p>Automatic Platform Optimization internal testing with WebPageTest demonstrated a very promising 72% reduction in Time to First Byte (TTFB) and 23% reduction to <a href="https://web.dev/fcp/">First Contentful Paint</a>. Follow <a href="/automatic-platform-optimizations-starting-with-wordpress/#the-benefits-of-automatic-platform-optimization">the original blog post</a> to learn more about our test setup and results analysis.</p>
    <div>
      <h2>Measuring performance with the Chrome User Experience Report</h2>
      <a href="#measuring-performance-with-the-chrome-user-experience-report">
        
      </a>
    </div>
    <p>In comparison to synthetic testing, Real User Monitoring (RUM) is invaluable in painting the picture of how a website performs in real-world conditions: on different form factors and variable connection types. Although noise to signal ratio could be high in RUM data, there is no substitute for measuring web performance in the wild.</p><p>We analyzed Google's <a href="https://developers.google.com/web/tools/chrome-user-experience-report">Chrome User Experience Report</a> of Automatic Platform Optimization websites and compared results from two months before enabling CrUX to the two months after. We present results of Time To First Byte, First Paint, First Contentful Paint, and Largest Contentful Paint.</p>
    <div>
      <h3>Time To First Byte by device</h3>
      <a href="#time-to-first-byte-by-device">
        
      </a>
    </div>
    <p>Time To First Byte (TTFB) is the time taken from the user or client making an HTTP request until the first byte arrives back to the browser.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7ukvHUfnTwdV6G9O2tInJK/da54e8a03550745d5c304c3664cacdb0/image1-15.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/nDmdI6LfhEhCmwrw8YAdE/6f4d30993e12970e71a0ad6efb0499b6/image6-5.png" />
            
            </figure><p>Automatic Platform Optimization improvements in the TTFB metric demonstrated the largest increase in the 'good' bucket and the largest decrease in the 'poor' bucket both on desktop and phone form factors among all metrics. The improvement in the 'poor' bucket on mobile demonstrates how Automatic Platform Optimization makes a difference even on slow connection types like 3G, 2G, slow 2G. Faster response times with Automatic Platform Optimization from edge servers translate directly into quicker TTFB timings, positively affecting all other performance measurements.</p>
    <div>
      <h3>First Paint by device</h3>
      <a href="#first-paint-by-device">
        
      </a>
    </div>
    <p>First Paint measures the first time the browser rendered any content. First Paint signifies the earliest point when something happens on the screen after a user requests a page. It is a good proxy for a user believing the website is not broken.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5crFujbvMLpxg5SWITmSm5/c8159070f9395e2b2a22b44bd860efad/image3-12.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6aaGYS8TwMdLUbyI75g7jA/69edacd19a63b2f3bbc013e056537fb8/image7-4.png" />
            
            </figure><p>Almost a 10% increase in the 'good' bucket on a desktop is the highlight for the First Paint metric. It's nice to see a clear trend of improvement in both desktop and phone data. It's also worth mentioning that the exact values used to define 'good’, 'moderate’, and the 'poor' buckets are picked arbitrarily for each timing metric. This trend means it's more important to look at the percentage of improvement rather than absolute values for each 'bucket'.</p>
    <div>
      <h3>First Contentful Paint by device</h3>
      <a href="#first-contentful-paint-by-device">
        
      </a>
    </div>
    <p>First Contentful Paint (FCP) metric measures how long a page takes to start rendering any text, image, non-white canvas, or SVG content. FCP is a good indicator of perceived speed as it portrays how long people wait to see the first signs of a site loading.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4DmAXL8e0YkFDplrWevrkS/f4f720ab35931d8b6afd5f7ff034f54d/image8-4.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6SPbEFcNeYbmiKYAkGnLZk/1b9f60e6c36257cb45ff879498aaa0ee/image5-12.png" />
            
            </figure><p>It is the third straight metric that has been improved in both form factors after customers activated Automatic Platform Optimization. FCP happens even later than the First Paint event. We can draw a hypothesis that Automatic Platform Optimization positively impacts the loading performance metrics of the site. Still, the later the event happens, the less impact Automatic Platform Optimization has on that particular metric.</p>
    <div>
      <h3>Largest Contentful Paint by device</h3>
      <a href="#largest-contentful-paint-by-device">
        
      </a>
    </div>
    <p>The Largest Contentful Paint (LCP) metric reports the render time for the largest image or text block visible within the viewport.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5VPFYu1C2Z4QJGbIUVuOTn/c41163eabc93b087c93a6da4a2f2a329/image4-11.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1UvAakum79HmgCxkdj9Hw3/4223477af4ccc5ca6dbf702ce2d3da5d/image2-10.png" />
            
            </figure><p>Our hypothesis holds ground with LCP as well. Interestingly enough, the positive impact of Automatic Platform Optimization activation is relatively equal on desktops and phones.</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>Overall, Automatic Platform Optimization consistently demonstrated better aggregate performance among sites we analyzed in TTFB, First Paint, FCP, and LCP metrics. Even more impressive are improvements on both desktop and phone form factors. It’s worth pointing out that apart from noticeable differences in hardware characteristics, phone data capture all mobile connection types from slow 2G to fast 4G.</p><p>We explored almost 200 websites with the activated Automatic Platform Optimization feature in Chrome User Experience Report data. To smooth the variance, we combined two months of data before and after Automatic Platform Optimization activation. To further decrease inaccuracy, we dropped a month’s worth of data that included the activation period. As an example, for a website that activated Automatic Platform Optimization last October, we used Chrome User Experience Report measurements from August and September as the <code>before</code> bucket. The <code>after</code> bucket combined data from November and December.</p><p>It is important to note that due to the limitations of iOS, Chrome User Experience Report mobile results don't include devices running Apple's mobile operating system.</p><p>Chrome User Experience Report data provides performance metrics per geographic location, form factor, or connection type. We analyzed aggregated data across all countries and connection types to focus on the overall performance.</p>
    <div>
      <h2>Extended Automatic Platform Optimization Functionality</h2>
      <a href="#extended-automatic-platform-optimization-functionality">
        
      </a>
    </div>
    <p>Since the product launch, we have been listening carefully to the customers' reports of Automatic Platform Optimization’s missing functionality or unexpected behavior. The number of different use cases our customers have underlines how broad the WordPress ecosystem is. One of the advantages of Automatic Platform Optimization utilizing the Workers platform is that we can quickly iterate and release in a matter of hours instead of days or weeks. Granted, some features like Cache By Device Type or subdomains support took us longer to build. Still, for apparent bugs or missing functionality, the ability to release on demand made all the difference for the team and our customers.</p><p>We start the second part of the report with a brief description of the features we have released since October. Afterward, we will paint a bigger picture of how Automatic Platform Optimization fits together with a broad WordPress plugins ecosystem.</p>
    <div>
      <h3>Smart caching for marketing query parameters</h3>
      <a href="#smart-caching-for-marketing-query-parameters">
        
      </a>
    </div>
    <p>By default Automatic Platform Optimization doesn’t cache pages with query parameters. One of the first feature requests from the community was to add caching support for marketing attribution (for example, UTMs) query parameters. We did exactly that, and the full list of the supported parameters is in <a href="https://support.cloudflare.com/hc/en-us/articles/360049822312#h_01EN42YA87TDRX47MSB2XC61Q9">the documentation</a>.</p>
    <div>
      <h3>Improved cache hit ratio</h3>
      <a href="#improved-cache-hit-ratio">
        
      </a>
    </div>
    <p>Cloudflare provides <a href="https://support.cloudflare.com/hc/en-us/articles/200172516">static caching</a> out of the box by default. The caching system for static content relies on file extensions to determine the content type. In contrast, HTML pages don't always have file extensions in the URL. That's why Automatic Platform Optimization caching relies on HTTP's <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation">content negotiation mechanism</a> for HTML content.</p><p>We check both the request's Accept and the response's Content-Type headers for the 'text/html' substring. When humans access sites on the Internet, browsers send correct Accept headers behind the scene. When bots access the sites, they don't always send Accept headers. Initially, the Automatic Platform Optimization cache passed all requests without a valid Accept header to the origin servers. When customers tried to migrate from using the "Cache Everything" page rule to only using Automatic Platform Optimization, they noticed extra load on the origin servers.. Now all GET and HEAD requests are checked against the Automatic Platform Optimization cache. The change noticeably improved the cache hit ratio for all Automatic Platform Optimization customers and enhanced page loads for good bots.</p>
    <div>
      <h3>Improved security</h3>
      <a href="#improved-security">
        
      </a>
    </div>
    <p><a href="https://portswigger.net/research/practical-web-cache-poisoning">Cache poisoning</a> is a common attack vector against any caching system. One of the benefits of Automatic Platform Optimization is that most of the logic runs on edge servers, and we can update it without any changes on the origin server. To mitigate potential cache poisoning, we released a new version to bypass caching if any of the following request headers are present:</p><ul><li><p>X-Host</p></li><li><p>X-Forwarded-Host</p></li><li><p>X-Original-URL</p></li><li><p>X-Rewrite-URL</p></li></ul><p>Additionally, any GET request <a href="https://portswigger.net/research/web-cache-entanglement#fatget">with a body</a> will bypass Automatic Platform Optimization caching.</p>
    <div>
      <h3>Page Rules integration</h3>
      <a href="#page-rules-integration">
        
      </a>
    </div>
    <p>Automatic Platform Optimization's primary goal is to improve page load performance while keeping the configuration as simple as possible. On the other hand, the Automatic Platform Optimization service should allow fine-tuning for advanced use cases. One such mechanism is Cloudflare's <a href="https://support.cloudflare.com/hc/en-us/articles/218411427-Understanding-and-Configuring-Cloudflare-Page-Rules-Page-Rules-Tutorial-">Page Rules</a>. As of today, Automatic Platform Optimization supports the following rules:</p><ul><li><p>Cache Level: Bypass</p></li><li><p>Cache Level: Ignore Query String</p></li><li><p>Cache Level: Cache Everything</p></li><li><p>Bypass Cache on Cookie (Biz and Ent plans only)</p></li><li><p>Edge Cache TTL</p></li><li><p>Browser Cache TTL</p></li></ul><p>For a detailed description, refer to the <a href="https://support.cloudflare.com/hc/en-us/articles/360049822312-Understanding-Automatic-Platform-Optimization-APO-with-WordPress#h_01ER098Z0DRS95ERCMZRV3022S">official documentation</a>.</p>
    <div>
      <h3>Subdomain Support</h3>
      <a href="#subdomain-support">
        
      </a>
    </div>
    <p>Automatic Platform Optimization aims to provide seamless integration with the WordPress ecosystem. It recognizes specific cookies for the most popular plugins like WooCommerce, JetPack, BigCommerce, Easy Digital Downloads, etc.</p><p>Currently, we limit Automatic Platform Optimization usage to WordPress sites. During the initial launch, we restricted Automatic Platform Optimization to run against root domains only, but we learned later of the high demand to run Automatic Platform Optimization on subdomains. To make it possible, we updated both the plugin and <a href="https://api.cloudflare.com/#zone-settings-change-automatic-platform-optimization-for-wordpress-setting">API</a> to allow Automatic Platform Optimization to run on subdomains. Three steps are required to enable Automatic Platform Optimization on a subdomain:</p><ul><li><p>Install version 3.8.7 or later of the Cloudflare WordPress plugin.</p></li><li><p>Log in using Global key. (You can only use an API token for the root domain.)</p></li><li><p>Enable APO. The subdomain displays in the list of hostnames in the card.</p></li></ul><p>The initial cost of $5 per month for Free plans includes running Automatic Platform Optimization against any number of subdomains.</p>
    <div>
      <h3>Caching by Device Type</h3>
      <a href="#caching-by-device-type">
        
      </a>
    </div>
    <p>The majority of site visits come from users accessing the web on <a href="https://www.perficient.com/insights/research-hub/mobile-vs-desktop-usage-study">mobile devices</a>. And website visitors expect sites to work well on mobile devices. In fact, responsive design is a recommended approach for websites. APO works well for responsive design websites because the cache's content will adjust to the client's screen size seamlessly. The alternative method is to serve different markup on mobile browsers.</p><p>Many popular WordPress plugins add a mobile-friendly theme to the site. For sites with such plugins installed, Automatic Platform Optimization breaks functionality by serving the same cached version for all users. As we learned about the growing number of customers with this problem, we looked for the solution. Cloudflare’s caching already has support for <a href="https://support.cloudflare.com/hc/en-us/articles/229373388-Understand-Cache-by-Device-Type-Enterprise-plans-only-">cache by device type</a> functionality, but it's only available for customers on the Enterprise plan. As was a case for the <a href="https://support.cloudflare.com/hc/en-us/articles/236166048">Bypass Cache on Cookie</a> page rule, we decided to include the functionality as part of the Automatic Platform Optimization offering. As a recap, Caching by Device Type relies on the User-Agent request header for detection. There are three types:</p><ul><li><p>Mobile</p></li><li><p>Tablet</p></li><li><p>Everything else</p></li></ul><p>For each type, the Cloudflare cache will store content in a separate bucket. To enable caching by device type, either navigate to the dashboard's Automatic Platform Optimization card or the Cloudflare WordPress plugin. We recommend using a single cache whenever possible because caching by device type can decrease cache hit ratio and increase the load on origin servers.</p>
    <div>
      <h3>Other noticeable changes</h3>
      <a href="#other-noticeable-changes">
        
      </a>
    </div>
    <p>There are many improvements including:</p><ul><li><p>Improved purging infrastructure of content from KV.</p></li><li><p>Extended automatic cache purging for categories and tags.</p></li><li><p>Addressed many edge cases for Google Fonts optimization.</p></li><li><p>Added support for HEAD requests.</p></li><li><p>Automated release pipeline for the Cloudflare WordPress plugin.</p></li></ul>
    <div>
      <h2>Improved WordPress plugins compatibility</h2>
      <a href="#improved-wordpress-plugins-compatibility">
        
      </a>
    </div>
    <p>There are over 50,000 WordPress plugins currently available for download, and because there are so many, we can't test the compatibility of Automatic Platform Optimization with each one individually. We do know, however, that it's vital to provide compatibility for the most popular plugins. Thanks to the vibrant community, we quickly learned about the most widely used issues with Automatic Platform Optimization caching. The plugins that experienced problems could be grouped into the following categories:</p><ul><li><p>Plugins with custom cookies</p></li><li><p>Plugins with geolocation functionality</p></li><li><p>Plugins with mobile themes</p></li><li><p>Plugins with AMP support</p></li><li><p>Plugins that generate HTML</p></li><li><p>Caching and optimizations plugins</p></li></ul><p>Let's review those categories and available solutions for improved compatibility.</p>
    <div>
      <h3>Plugins with custom cookies</h3>
      <a href="#plugins-with-custom-cookies">
        
      </a>
    </div>
    <p>One of the critical features Automatic Platform Optimization provides out of the box is cookie-based rules to bypass APO caching. For any plugin that uses custom cookies, Automatic Platform Optimization requires extending the rules. We have a list of <a href="https://support.cloudflare.com/hc/en-us/articles/360049822312#h_01EQ44V6KRFM6Z0F06MM0EJGJ5">supported plugins</a> that uses our cookies bypass logic.</p>
    <div>
      <h3>Plugins with geolocation functionality</h3>
      <a href="#plugins-with-geolocation-functionality">
        
      </a>
    </div>
    <p>This broad category of plugins relies on geolocation information based on the client's (visitor) IP address (connecting to Cloudflare) to provide its functionality. Early on, we had a misconfiguration in Automatic Platform Optimization functionality that resulted in sending a dummy IP address in the CF-Connecting-IP request header that was forwarded to the origin server.</p><p>This behavior effectively broke the functionality of the widely used Wordfence Security plugin. We promptly released a fix. Because we use Cloudflare Workers internally, Cloudflare Workers treated Automatic Platform Optimization requests sent to the origin as cross-zone requests due to security concerns. As a result, <a href="https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-">the CF-Connecting-IP</a> header value was replaced with a dummy IP address. The change was to send the Automatic Platform Optimization worker's subrequest to the origin as a same-zone request to pass the real client IP without a security concern. Also, Automatic Platform Optimization now sends the client's IP via the X-Forwarded-For request header to the origin to improve plugin compatibility.</p>
    <div>
      <h3>Plugins with mobile themes</h3>
      <a href="#plugins-with-mobile-themes">
        
      </a>
    </div>
    <p>There are several WordPress plugins that render custom themes for mobile visitors. Those plugins rely on the browser's User-Agent to detect visitors from mobile devices. In December, we released Automatic Platform Optimization support for the "Cache by device type" feature. With a single configuration change, you can activate a separate cache based on the device type: mobile, tablet, and everything else. You can learn more about the feature in the <a href="https://support.cloudflare.com/hc/en-us/articles/360049822312#h_01ERZ6QHBGFVPSC44SJAC1YM6Q">official documentation</a>.</p>
    <div>
      <h3>Plugins with AMP support</h3>
      <a href="#plugins-with-amp-support">
        
      </a>
    </div>
    <p>The AMP (<a href="https://amp.dev/">Accelerated Mobile Pages</a>) project's goal is to make the web, and, in particular, the mobile web, much more pleasant to surf. The AMP HTML framework is designed to help web pages load quickly and avoid distracting the user with irrelevant content.</p><p>The most popular AMP WordPress plugins render AMP-compatible markup when the page URL contains the amp= query parameter. AMP markup is a subset of HTML with several restrictions and we looked into possible solutions to provide Automatic Platform Optimization caching for AMP pages. It requires a separate cache for AMP pages similar to the "Cache by device type" feature. Considering Google's recent push with Core Web Vitals, the AMP format's importance will decrease going forward. Based on the complexity of supporting dedicated AMP caching and Google's deprioritization of the AMP format, we decided to bypass Automatic Platform Optimization caching of AMP pages.</p><p>There are two possible approaches for caching AMP pages. The first one is to change the URL schema for AMP pages from, for example, site.com/page/?amp= to site.com/amp/page/. With this option, Automatic Platform Optimization caches AMP pages out of the box. Another solution is to activate the "Cache Everything" Page rule for AMP pages served with amp= query parameter. Note that AMP pages will require manual cache purging in both cases on content change.</p>
    <div>
      <h3>Plugins that generate HTML</h3>
      <a href="#plugins-that-generate-html">
        
      </a>
    </div>
    <p>Using Automatic Platform Optimization with Page Rules makes it possible to:</p><ul><li><p>Bypass caching pages that contain CAPTCHAs.</p></li><li><p>Set Edge TTL for pages that contain nonces or server-rendered ads to six hours or shorter.</p></li></ul>
    <div>
      <h3>Caching and optimizations plugins</h3>
      <a href="#caching-and-optimizations-plugins">
        
      </a>
    </div>
    <p>Among the most popular caching and optimizations WordPress plugins are LiteSpeed Cache, W3 Total Cache, WP Rocket, WP Fastest Cache, WP Super Cache, Autoptimize. To successfully activate Advanced Platform Optimization when any of the plugins above already present, follow these steps:</p><ul><li><p><a href="https://support.cloudflare.com/hc/en-us/articles/360049822312#h_01EKKWPM2KC6H9CD0ATX98KG1C">Install</a> and activate the Cloudflare WordPress plugin.</p></li><li><p>Enable Automatic Platform Optimization in the plugin.</p></li><li><p>Clear any server cache used via other plugins.</p></li><li><p>Verify that your origin starts serving the response header "cf-edge-cache: cache,platform=wordpress".</p></li></ul><p>That should make caching plugins and Automatic Platform Optimization compatible.</p><p>In using optimizations features inside the plugins, additional steps are necessary to integrate with Automatic Platform Optimization. Any of the following plugin's optimizations require subsequent purging of Cloudflare cache:</p><ul><li><p>JavaScript minification and async-loading</p></li><li><p>CSS minification, inlining, and aggregation</p></li><li><p>HTML minification</p></li><li><p>Images optimization and lazy-loading</p></li><li><p>Google fonts optimizations</p></li></ul><p>There are three potential solutions we discuss in the order of preference.</p>
    <div>
      <h4>1. Use Cloudflare products</h4>
      <a href="#1-use-cloudflare-products">
        
      </a>
    </div>
    <p>Most of the optimizations are possible with Cloudflare today:</p><ul><li><p>Auto Minify provides minification for HTML, CSS, and JavaScript</p></li><li><p>Rocket Loader provides JavaScript lazy loading</p></li><li><p>Mirage and Image-resizing allows image optimization and lazy-loading</p></li><li><p>Advanced Platform Optimization optimizes Google fonts out of the box</p></li></ul>
    <div>
      <h4>2. Activate plugins integration with Cloudflare</h4>
      <a href="#2-activate-plugins-integration-with-cloudflare">
        
      </a>
    </div>
    <ul><li><p>WP Rocket <a href="https://docs.wp-rocket.me/article/18-using-wp-rocket-with-cloudflare">integrates</a> with Cloudflare API.</p></li><li><p>WP Fastest Cache <a href="https://www.wpfastestcache.com/tutorial/wp-fastest-cache-cloudflare/">integrates</a> with Cloudflare API.</p></li><li><p>W3 Total Cache <a href="https://kinsta.com/blog/w3-total-cache/#how-to-set-up-w3-total-cache-with-the-cloudflare-extension">integrates</a> with Cloudflare API. Make sure to enable the Page Caching option.</p></li></ul>
    <div>
      <h4>3. Integration with Cloudflare cache purging</h4>
      <a href="#3-integration-with-cloudflare-cache-purging">
        
      </a>
    </div>
    <p>The rest of the plugins in the list, when producing content optimizations, require triggering of Cloudflare cache purging manually or via <a href="https://api.cloudflare.com/#zone-purge-files-by-url">API</a>:</p><ul><li><p>LiteSpeed Cache</p></li><li><p>WP Super Cache</p></li><li><p>Autoptimize</p></li></ul>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>Automatic Platform Optimization is compatible with the most popular caching plugins. Content optimizations should be preferably migrated to Cloudflare offerings. Alternatively, plugins require triggering Cloudflare cache purging via API integration. The action of the last resort is to disable plugins optimizations but keep caching functionality.</p><p>We work closely with the WordPress plugins community to improve compatibility with Advanced Platform Optimization.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Automatic Platform Optimization demonstrated improved performance metrics in both synthetic and real-world settings. The public Chrome User Experience Report dataset proved to be an invaluable source of RUM metrics for web performance analysis. Automatic Platform Optimization showed noticeable improvements on desktops and phones. TTFB is the most improved metric, but we also noticed positive changes in the First Paint, First Contentful Paint, and Largest Contentful Paint metrics.</p><p>It has been intensive and rewarding several months since the Automatic Platform Optimization launch, and we greatly increased Automatic Platform Optimization applicability based on customer feedback. Our <a href="https://community.cloudflare.com/">community forum</a> is a great place to get help and ask questions about Cloudflare products, including Advanced Platform Optimization.</p><p>There are more exciting Automatic Platform Optimization improvements the team is actively working on, and we can't wait to share them. Stay tuned!</p> ]]></content:encoded>
            <category><![CDATA[Automatic Platform Optimization]]></category>
            <category><![CDATA[WordPress]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Performance]]></category>
            <guid isPermaLink="false">3f2zJqUMBglhwX15U1lOPm</guid>
            <dc:creator>Yevgen Safronov</dc:creator>
        </item>
        <item>
            <title><![CDATA[The benefits of serving stale DNS entries when using Consul]]></title>
            <link>https://blog.cloudflare.com/the-benefits-of-serving-stale-dns-entries-when-using-consul/</link>
            <pubDate>Mon, 08 Mar 2021 14:00:00 GMT</pubDate>
            <description><![CDATA[ We use Consul for service discovery, and we’ve deployed a cluster that spans several of our data centers. We were aware from the start that the DNS query latencies were not great from certain parts of the world that were furthest away from these data centers. ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>Introduction</h2>
      <a href="#introduction">
        
      </a>
    </div>
    <p>We use <a href="https://www.consul.io/">Consul</a> for service discovery, and we’ve deployed a cluster that spans several of our data centers. This cluster exposes HTTP and DNS interfaces so that clients can query the Consul catalog and search for a particular service and the majority of the clients use DNS. We were aware from the start that the DNS query latencies were not great from certain parts of the world that were furthest away from these data centers. This, together with the fact that we use <a href="https://en.wikipedia.org/wiki/DNS_over_TLS">DNS over TLS</a>, results in some long latencies. The TTL of these names being low makes it even more impractical when resolving these names in the hot path.</p><p>The usual way to solve these issues is by caching values so that at least subsequent requests are resolved quickly, and this is exactly what our resolver of choice, <a href="https://www.nlnetlabs.nl/projects/unbound/about/">Unbound</a>, is configured to do. The problem remains when the cache expires. When it expires, the next client will have to wait while Unbound resolves the name using the network. To have a low recovery time in case some service needs to failover and clients need to use another address we use a small TTL (30 seconds) in our records and as such cache expirations happen often.</p><p>There are at least two strategies to deal with this: prefetching and stale cache.</p>
    <div>
      <h2>Prefetching</h2>
      <a href="#prefetching">
        
      </a>
    </div>
    <p>When prefetching is turned on, the server tries to refresh DNS records in the background before they expire. In practice, the way this works is: if an entry is served from cache and the TTL is less than 10% of the lifetime of the records, the server responds to the client, but in the background, it dispatches a job to refresh the record across the network. If it all goes as planned, the entry is refreshed in the cache before the TTL expires, and no client is ever left waiting for the network resolution.</p><p>This works very well for records that are accessed frequently, but poses issues in two situations: records that are accessed infrequently and records that have a small TTL. In both cases it is unlikely that a prefetch would be triggered, and so the cache expires and the next client will have to wait for the network resolution.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6NcCnqSXw360PiHjNzeq2y/4e2305dada9a66609edb4fc4264d20e5/image1-6.png" />
            
            </figure><p>In our case, the records have a 30 second TTL, so frequently no requests come in during the yellow "prefetch" stage, which bumps the records out of the cache and causes the next client to have to wait for the slow network resolution. Prefetching was already turned on in our Unbound configuration but this still was not enough for our use case.</p>
    <div>
      <h2>Stale cache</h2>
      <a href="#stale-cache">
        
      </a>
    </div>
    <p>Another option is to serve stale records from the cache while we dispatch a job to refresh the record in the background without keeping the client waiting for the response. This would provide benefits in two different scenarios:</p><ul><li><p>General high latency - even after the TTL expires subsequent attempts will be returned from cache if the response takes too long to arrive.</p></li><li><p>Consul/network blips - if for some reason Consul is unavailable/unreachable, there is still a period of time that expired responses can be used instead of failing resolution.</p></li></ul><p>The first case is exactly our current scenario.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ixBixKeeIwU63f485mr2U/18844f87438211049fcfcf923e12c231/image7.png" />
            
            </figure><p>Being able to serve stale entries from the cache for a period after the TTL expires affords us some time in which we can return a result to a client either immediately or after some small amount of time has passed. The latter is the behaviour that we are looking for which also makes us compliant with <a href="https://www.rfc-editor.org/rfc/rfc8767">RFC 8767</a>, “Serving Stale Data to Improve DNS Resiliency”, published March 2020.</p>
    <div>
      <h3>Previous dealings with Unbound's stale cache</h3>
      <a href="#previous-dealings-with-unbounds-stale-cache">
        
      </a>
    </div>
    <p>Stale cache had been tried before at Cloudflare in 2017, and at that time, we encountered two problems:</p><p><b>1. Unbound could serve stale records from cache indefinitely</b>We could solve this through configuration that did not exist in 2017, but we had to test it.</p><p><b>2. Unbound serves negative/incomplete information from the expired cache</b>It was reported that Unbound would serve incomplete chains of responses to clients (for example, a CNAME record with no corresponding A/AAAA record).</p><p>This turned out to be unconfirmed but it is a failure mode that nevertheless we wanted to make sure Unbound could handle since it would be possible for parts of the response chain to be purged from the stale cache before others.</p>
    <div>
      <h3>Test Configuration</h3>
      <a href="#test-configuration">
        
      </a>
    </div>
    <p>As mentioned before we would need to test a current version of Unbound, come up with an up-to-date stale cache configuration, and test the scenarios that posed problems when we last tried to use it plus any others that we came up with. The Unbound version used for tests was 1.13.0 and the stale cache was configured thus:</p><ul><li><p><i>serve-expired: yes</i> - enable the stale cache.</p></li><li><p><i>serve-expired-ttl: 3600</i> - this limits the serving of expired resources to one hour after they expire and no response from upstream was obtained.</p></li><li><p><i>serve-expired-client-timeout: 500</i> - serve from stale cache only when upstream takes longer than 500ms to respond.</p></li></ul><p>The option <i>serve-expired-ttl-reset</i> was considered, which would cause the records to never expire, even with the upstream down indefinitely as long as there are regular requests for them, but it was deemed too dangerous since it could potentially last forever and applies to all entries.</p><p>Example consul zone: <b>service1.sd</b>.</p><p>While resolving this name we end up with:</p>
            <pre><code>;; ANSWER SECTION:
service1.sd. 120 IN CNAME service1.query.consul.
service1.query.consul. 30 IN A 192.0.2.1
 
;; Query time: 230 msec</code></pre>
            <p>If we dump Unbound's cache (unbound-control dump_cache), we can find the entries there:</p>
            <pre><code>service1.query.consul. 23  IN  A   192.0.2.1
service1.sd.   113 IN  CNAME   service1.query.consul.</code></pre>
            <p>If we wait for the TTL of these entries to expire and dump the cache again, we notice that they don't show up anymore:</p>
            <pre><code>➜ unbound-control dump_cache | grep -e query.consul -e service1
➜</code></pre>
            <p>But if we block access to the Consul resolver, we can see that still the entries are returned:</p>
            <pre><code>;; ANSWER SECTION:
service1.sd. 119 IN CNAME service1.query.consul.
service1.query.consul. 30 IN A 192.0.2.1
 
;; Query time: 503 msec</code></pre>
            <p>Notice that Unbound waited 500ms before returning a response, which was the value we configured. This also shows that the dump cache method does not return expired entries even though they are present. So far so good.</p>
    <div>
      <h5><b>Test - Unbound could serve stale records from cache indefinitely</b></h5>
      <a href="#test-unbound-could-serve-stale-records-from-cache-indefinitely">
        
      </a>
    </div>
    <p>After 3600 seconds pass we again try to resolve the same name:</p>
            <pre><code>➜ dig  service1.sd. @127.0.0.1
 
; &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; service1.sd. @127.0.0.1
;; global options: +cmd
;; connection timed out; no servers could be reached</code></pre>
            <p>Dig gave up on waiting for a response from Unbound. So we see that after the configured time, Unbound will indeed stop serving the stale record, even if it has been requested recently. This is due to <i>serve-expired-ttl: 3600</i> and <i>serve-expired-ttl-reset</i> being set to "no" by default. These options were not available when we first tried Unbound’s stale cache.</p>
    <div>
      <h5><b>Test - Unbound serves negative/incomplete information from the expired cache</b></h5>
      <a href="#test-unbound-serves-negative-incomplete-information-from-the-expired-cache">
        
      </a>
    </div>
    <p>Since the record we are resolving includes a CNAME and an A record with different TTLs, we will try to see if Unbound can be made to return an incomplete chain (CNAME with no A record).</p><p>We start by having both entries in cache, and block connections to the Consul resolver. We then remove from the cache the A entry:</p>
            <pre><code>$ /usr/sbin/unbound-control flush_type service1.query.consul. A
ok</code></pre>
            <p>Now we attempt to query:</p>
            <pre><code>$ dig  service1.sd. @127.0.0.1
...
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: SERVFAIL, id: 9532
;; Query time: 22 msec</code></pre>
            <p>Nothing was returned which is the result we were expecting.</p><p>Another scenario we wanted to test was to see if when <i>serve-expired-ttl</i> + A's TTL had passed, the CNAME would be returned on its own.</p>
            <pre><code>➜ dig  service1.sd. @127.0.0.1
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 48918
;; ANSWER SECTION:
service1.sd. 48 IN CNAME service1.query.consul.
service1.query.consul. 30 IN A 192.0.2.1
;; Query time: 430 msec
;; WHEN: Thu Dec 31 17:07:55 WET 2020
 
➜ dig  service1.sd. @127.0.0.1
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: SERVFAIL, id: 42432
;; Query time: 509 msec
;; WHEN: Thu Dec 31 17:07:56 WET 2020</code></pre>
            <p>We lowered <i>serve-expired-ttl</i> to 40 to help testing the issue and we were able to see that as soon as the A entry was deemed not serve-able, the CNAME was also not returned, which is the behaviour that we want.</p><p>One last thing that we wanted to test was if the cache was really refreshed in the background while the stale entry was returned. <a href="https://developer.apple.com/download/more/?q=Additional%20Tools">Network Link Conditioner</a> was used to simulate high latency:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2LzVKSaIVIOaKuMuHbq9Fa/578619d90974ef897ae8e5d58ca9fe12/image16.png" />
            
            </figure>
            <pre><code>➜ dig service1.service.consul @CONSUL_ADDRESS
 
;; ANSWER SECTION:
service1.service.consul. 60 IN A 192.0.2.10
service1.service.consul. 60 IN A 192.0.2.12
 
;; Query time: 3053 msec</code></pre>
            <p>We can see that the artificial latency is working. We can now test if changes to the address are actually reflected on the consul record even though a stale record is served at first:</p>
            <pre><code>➜ dig service2.service.consul @127.0.0.1
...
;; ANSWER SECTION:
service2.service.consul. 30 IN A 192.0.2.100
 
;; Query time: 501 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Jan 02 13:00:36 WET 2021
;; MSG SIZE  rcvd: 89
 
➜ dig service2.service.consul @127.0.0.1
...
;; ANSWER SECTION:
service2.service.consul. 58 IN A 192.0.2.200
 
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Jan 02 13:00:39 WET 2021
;; MSG SIZE  rcvd: 89</code></pre>
            <p>We can see that the first attempt was served from the stale cache, since the address was already changed on Consul to <i>192.0.2.200</i>, and the query time was 500ms. The next attempt was served from the fresh cache, hence the 0ms response time, and so we know that the cache was refreshed in the background.</p>
    <div>
      <h4><b>Test notes</b></h4>
      <a href="#test-notes">
        
      </a>
    </div>
    <p>All the test scenarios completed successfully, even though we did find an <a href="https://github.com/NLnetLabs/unbound/issues/394">issue</a> that has since been fixed upstream. We realised that the prefetching logic blocked the cache while it attempted to refresh the entry, which prevented stale entries from being served if the upstream was unresponsive. This fix is included in version 1.13.1.</p>
    <div>
      <h2>Deployment status</h2>
      <a href="#deployment-status">
        
      </a>
    </div>
    <p>This change has already been deployed to all of our data centers, and while the change addressed our original use case, there were some interesting side-effects as can be seen from the graphs below.</p>
    <div>
      <h3>Decreased in-flight requests</h3>
      <a href="#decreased-in-flight-requests">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5SEqkHk3xrVWSixpgdbdZa/7efa3f7c24e00772122d5b2e41efc353/image2-2.png" />
            
            </figure><p>The graph above is from the Toronto data center which received the change at approximately 14:00 UTC. We can observe an attenuated curve, which indicates that spikes in the number of in-flight requests were probably caused by slow/unresponsive upstreams which are now served a stale response after a short while.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/VG1RTOCYpAKbaGFm1wIzo/42901205b6abb8db0fb4d2056555eb42/image5-2.png" />
            
            </figure><p>The same graph from the Perth data center, which received the change on a later day.</p>
    <div>
      <h3>Decrease in P99 latency</h3>
      <a href="#decrease-in-p99-latency">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3sHaBdYvhCW0SdPdPLm03F/14d71c18a9e1e6ae6fa99f15e4edab38/image15.png" />
            
            </figure><p>The graph above is from the Lisbon data center_,_ which received the change at approximately 12:37 UTC. We can see that the long tail (P99) of request latencies decreases dramatically as we are now able to serve a response to clients in more situations without having them wait for a slow upstream network resolution that might not even succeed.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4205xzfOSup4fdebmcwW5G/d1c7d53dfb89066328eb9db64d3abf95/image10-2.png" />
            
            </figure><p>The effect is even more dramatic on the Paris data center.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/61OoMQx3e3PjZVzVvQoSUe/c70e5b82c7349897757ec5658ef36d03/image8-2.png" />
            
            </figure><p>The decrease in P99 latencies directly correlates to the start of serving stale entries, even though there are not many of them. In the graph above we can observe the number of stale records served per second for the same data center, using the last 3 minutes of datapoints.</p>
    <div>
      <h3>Decreased general error rate</h3>
      <a href="#decreased-general-error-rate">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/49nNtzXobSQtD0tgnddiJL/7505715c40eeb1d2767a6d7e33ea86bc/image12.png" />
            
            </figure><p>This graph is from our Perth data center, which received the change on February 8. This is explained by now being able to serve some requests to unresponsive/slow upstreams, which previously would have resulted in a failed request.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Pj6PgH2tsWfgRjFIOvZ7P/83f7dfaa8623dc3acc694ff04953bddc/image19.png" />
            
            </figure><p>Graph from the Vientiane data center, which received the change on February 1.</p>
    <div>
      <h3>Less jitter on the rate of load balancer queries by RRDNS</h3>
      <a href="#less-jitter-on-the-rate-of-load-balancer-queries-by-rrdns">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LFLwd8W5wriMKlsZZdCXG/d06e8adc686b4aec2c4cca858beafd56/image11.png" />
            
            </figure><p>Another graph from the Perth data center, which received the change on February 8. An explanation for this change is that resolvers usually retry after a small amount of time when they don't get any response, and so by returning a stale response instead of keeping the client waiting (and retrying), we prevent a surge of new queries for expired and slow to resolve records.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Nlj6ruekdbxc5e86cDIVd/ef1c0ea3d9de713c60fd28ec247258a8/image18.png" />
            
            </figure><p>A graph from the Doha data center, which received the change on February 1.</p>
    <div>
      <h3>Miscellaneous Unbound metrics</h3>
      <a href="#miscellaneous-unbound-metrics">
        
      </a>
    </div>
    <p>This change also had a positive effect on several Unbound-specific metrics, below are several graphs from the Perth data center that received the change on February 8.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6tvgfdPirOIApYCRxmzujb/945dea0b77381302fd9a931ccd8389ee/image6-2.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1TnCvyvE1SxFM02ulD7wOA/dbc2b15548cf92494dcc439d17d2f2ab/image13.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1KnVnBNkHrtUnkuC4X4rlN/6dbafa822edc14fbb03c077636e59b7c/image14.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1K0X5VnGlDWyfj4GXhHwKR/f676986d1c901998425a855e10ac4a2e/image4-4.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/78YTgVILYTXNqtkZCgPZhu/5a6aeb35e06bb620000291a16bf69412/image9-1.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3lbt8d6fKHtHIi84k0SnyW/f2cd288ec63f34e2be4c5f938b658028/image17.png" />
            
            </figure><p>How it started vs how it's going</p>
    <div>
      <h3>Further improvements</h3>
      <a href="#further-improvements">
        
      </a>
    </div>
    <p>In the future, we would like to tweak the <i>serve-expired-client-timeout</i> value, which is currently set to 500ms. It was chosen conservatively, at a time when we were cautiously experimenting with a feature that had been problematic in the past, and our gut feeling is that it can be at least halved without causing issues to further improve the client’s experience. There is also the possibility of using different values per data center, for example picking up the P90 resolve latency value which differs per datacenter, and this is something that we want to explore further.</p>
    <div>
      <h2>Summary</h2>
      <a href="#summary">
        
      </a>
    </div>
    <p>We are enabling Unbound to return expired entries from the cache whenever an upstream takes longer than 500ms to respond, while refreshing the cache in the background, unless 3600 seconds have elapsed from the record's original TTL.</p> ]]></content:encoded>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Cache]]></category>
            <guid isPermaLink="false">64s0ckd7FF53Lw8Q48zi1h</guid>
            <dc:creator>André Cruz</dc:creator>
        </item>
        <item>
            <title><![CDATA[Introducing: Smarter Tiered Cache Topology Generation]]></title>
            <link>https://blog.cloudflare.com/introducing-smarter-tiered-cache-topology-generation/</link>
            <pubDate>Thu, 18 Feb 2021 20:01:00 GMT</pubDate>
            <description><![CDATA[ Announcing a fundamental improvement to Argo Tiered Cache we’re calling Smart Tiered Cache Topology. When enabled, Argo Tiered Cache will now dynamically select the single best upper tier for each of your website’s origins while providing tiered cache analytics.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Caching is a magic trick. Instead of a customer’s origin responding to every request, Cloudflare’s 200+ data centers around the world respond with content that is cached geographically close to visitors. This dramatically improves the load performance for web pages while decreasing the bandwidth costs by having Cloudflare respond to a request with cached content.</p><p>However, if content is not in cache, Cloudflare data centers must contact the origin server to receive the content. This isn’t as fast as delivering content from cache. It also places load on an origin server, and is more costly compared to serving directly from cache. These issues can be amplified depending on the geographic distribution of a website’s visitors, the number of data centers contacting the origin, and the available origin resources for responding to requests.</p><p>To decrease the number of times our network of data centers communicate with an origin, we organize data centers into tiers so that only upper-tier data centers can request content from an origin and then they spread content to lower tiers. This means content that loads faster for visitors, is cheaper to serve, and reduces origin resource consumption.</p><p>Today, I’m thrilled to announce a fundamental improvement to Argo Tiered Cache we’re calling Smart Tiered Cache Topology. When enabled, Argo Tiered Cache will now dynamically select the <b>single</b> best upper tier for each of your website’s origins while providing tiered cache analytics showing how your custom topology is performing.</p>
    <div>
      <h3>Smarter Tiered Cache Topology Generation</h3>
      <a href="#smarter-tiered-cache-topology-generation">
        
      </a>
    </div>
    <p>Tiered Cache is part of <a href="/argo/">Argo</a>, a constellation of products that analyzes and optimizes routing decisions across the global Internet in real-time by processing information from every Cloudflare request to determine which routes to an origin are fast, which are slow, and what the optimum path from visitor to content is at any given moment. Previously, Argo Tiered Cache would use a static collection of upper-tier data centers to communicate with the origin. With the improvements we’re announcing today, Tiered Cache can now dynamically find the single best upper tier for an origin using Argo performance and routing data. When Argo is enabled and a request for particular content is made, we collect latency data for each request to pick the optimal path. Using this latency data, we can determine how well any upper-tier data center is connected with an origin and can empirically select the best data center with the lowest latency to be the upper tier for an origin.</p>
    <div>
      <h3>Argo Tiered Cache</h3>
      <a href="#argo-tiered-cache">
        
      </a>
    </div>
    <p>Taking one step back, tiered caching is a practice where Cloudflare’s network of global data centers are subdivided into a hierarchy of upper tiers and lower tiers. In order to control bandwidth and number of connections between an origin and Cloudflare, only upper tiers are permitted to request content from an origin and must propagate that information to the lower tiers. In this way, Cloudflare data centers first talk to each other to find content before asking the origin. This practice improves bandwidth efficiency by limiting the number of data centers that can ask the origin for content, reduces origin load, and makes websites more cost-effective to operate. Argo Tiered Cache customers only pay for data transfer between the client and edge, and we take care of the rest. Tiered caching also allows for improved performance for visitors, because distances and links traversed between Cloudflare data centers are generally shorter and faster than the links between data centers and origins.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2QDxHRN0EK06gPXmgCImTV/df986528a51c74220820cd96aca2651f/image5-7.png" />
            
            </figure><p>Previously, when Argo Tiered Cache was enabled for a website, several of Cloudflare’s largest and most-connected data centers were determined to be upper tiers and could pull content from an origin on a cache MISS. While utilizing a topology consisting of numerous upper-tier data centers may be globally performant, we found that cost-sensitive customers generally wanted to find the single best upper tier for their origin to ensure efficient data transfer of their content to Cloudflare’s network. We built Smart Tiered Cache Topology for this reason.</p>
    <div>
      <h3>How to enable Smart Tiered Cache Topology</h3>
      <a href="#how-to-enable-smart-tiered-cache-topology">
        
      </a>
    </div>
    <p>When you enable Argo Tiered Cache, Cloudflare now by default concentrates connections to origin servers so they come from a single data center. This is done without needing to work with our Customer Success or Solutions Engineering organization to custom configure the best single upper tier. Argo customers can generate this topology by:</p><ul><li><p>Logging into your Cloudflare account.</p></li><li><p>Navigating to the Traffic tab in the dashboard.</p></li><li><p>Ensuring you have Argo enabled.</p></li><li><p>From there, Non-Enterprise Argo customers will automatically be enrolled in Smart Tiered Cache Topology without needing to make any additional changes.</p></li></ul><p>Enterprise customers can select the type of topology they’d like to generate.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3oh6DzpSOiNYBZAoGnrMpp/dbd1c241eb5c3e79d671aa8e053cb0a9/image2-14.png" />
            
            </figure><p>Self-serve Argo customers are automatically enrolled in Smart Tiered Cache Topology</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/24hbML02D31EjENDUdc8cs/61630f9cef8aa4a963b409987ce11bb7/image3-9.png" />
            
            </figure><p>Enterprise customers can determine the tiered cache topology that works best for them.</p>
    <div>
      <h3>More data, fewer problems</h3>
      <a href="#more-data-fewer-problems">
        
      </a>
    </div>
    <p>Once enabled, in addition to performance and cost improvements, Smart Tiered Cache Topology also delivers summary analytics for how the upper tiers are performing so that you can monitor the cost and performance benefits your website is receiving. These analytics are available in the Cache Tab of the dashboard in the Tiered Cache section. The “Primary Data Center” and “Secondary Data Center” fields show you which data centers were determined to be the best upper tier and failover for your origin. “Cached Hits” and the “Hit Ratio” shows you the proportion of requests that were served by the upper tier and how many needed to be forwarded on to the origin for a response. “Bytes Saved” indicates the total transfer from the upper-tier data center to the lower tiers, showing the total bandwidth saved by having Cloudflare’s lower tier data centers ask the upper tiers for the content instead of the origin.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1vCbtYf2piNcIAYCXl5FwH/2c5b98c4e4765b6e120575c17b81c4dd/image4-4.png" />
            
            </figure><p>Smart Tiered Cache Topology works with Cloudflare’s existing products to deliver you a seamless, easy, and performant experience that saves you money and provides you useful information about how your upper tiers are working with your origins. Smart Tiered Cache Topology stands on the shoulders of some of the most resilient and useful products at Cloudflare to provide even more benefits to webmasters.</p><p>If you’re interested in seeing how Argo and Smart Tiered Cache Topology can benefit your web property, please login to your Cloudflare account and find more information in the Traffic tab of the dashboard <a href="https://dash.cloudflare.com/traffic">here</a>.</p> ]]></content:encoded>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Tiered Cache]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">5gzjOiOBX0V72X6JyeOjS0</guid>
            <dc:creator>Alex Krivit</dc:creator>
        </item>
    </channel>
</rss>