
<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>Sat, 04 Apr 2026 08:50:39 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Slicing and Dicing Instant Logs: Real-time Insights on the Command Line]]></title>
            <link>https://blog.cloudflare.com/instant-logs-on-the-command-line/</link>
            <pubDate>Mon, 07 Feb 2022 17:04:28 GMT</pubDate>
            <description><![CDATA[ Today, I am going to introduce you to Instant Logs in your terminal ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5x3aLlINzMShJK4anPOXaS/17359d254b8f621e69e874dbcd19f1df/image3-10-2.png" />
            
            </figure><p>During Speed Week 2021 we announced a new offering for Enterprise customers, <a href="/how-we-built-instant-logs/">Instant Logs</a>. Since then, the team has not slowed down and has been working on new ways to enable our customers to consume their logs and gain powerful insights into their HTTP traffic in real time.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4vhooHoc2Xv3yigrIOQBkW/362e50f9e8c80818a2888e20ffbdd8c4/image1-6.png" />
            
            </figure><p>We recognize that as developers, UIs are useful but sometimes there is the need for a more powerful alternative. Today, I am going to introduce you to Instant Logs in your terminal! In order to get started we need to install a few open-source tools to help us:</p><ul><li><p><a href="https://github.com/vi/websocat">Websocat</a> - to connect to WebSockets.</p></li><li><p><a href="https://github.com/rcoh/angle-grinder">Angle Grinder</a> - a utility to slice-and-dice a stream of logs on the command line.</p></li></ul>
    <div>
      <h2>Creating an Instant Log’s Session</h2>
      <a href="#creating-an-instant-logs-session">
        
      </a>
    </div>
    <p>For enterprise zones with access to Instant Logs, you can create a new session by sending a POST request to our jobs' endpoint. You will need:</p><ul><li><p>Your Zone Tag / ID</p></li><li><p>An Authentication Key or an API Token with at least the Zone Logs Read permission</p></li></ul>
            <pre><code>curl -X POST 'https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/logpush/edge/jobs' \
-H 'X-Auth-Key: &lt;KEY&gt;' \
-H 'X-Auth-Email: &lt;EMAIL&gt;' \
-H 'Content-Type: application/json' \
--data-raw '{
    "fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID",
    "sample": 1,
    "filter": "",
    "kind": "instant-logs"
}'</code></pre>
            
    <div>
      <h3>Response</h3>
      <a href="#response">
        
      </a>
    </div>
    <p>The response will include a new field called <code>destination_conf</code>. The value of this field is your unique WebSocket address that will receive messages directly from our network!</p>
            <pre><code>{
    "errors": [],
    "messages": [],
    "result": {
        "id": 401,
        "fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID",
        "sample": 1,
        "filter": "",
        "destination_conf": "wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2",
        "kind": "instant-logs"
    },
    "success": true
}</code></pre>
            
    <div>
      <h2>Connect to WebSocket</h2>
      <a href="#connect-to-websocket">
        
      </a>
    </div>
    <p>Using a CLI utility like <a href="https://github.com/vi/websocat">Websocat</a>, you can connect to the WebSocket and start immediately receiving logs of line-delimited JSON.</p>
            <pre><code>websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2
{"ClientRequestHost":"example.com","ClientRequestMethod":"GET","ClientRequestPath":"/","EdgeEndTimestamp":"2022-01-25T17:23:05Z","EdgeResponseBytes":363,"EdgeResponseStatus":200,"EdgeStartTimestamp":"2022-01-25T17:23:05Z","RayID":"6d332ff74fa45fbe","sampleInterval":1}
{"ClientRequestHost":"example.com","ClientRequestMethod":"GET","ClientRequestPath":"/","EdgeEndTimestamp":"2022-01-25T17:23:06Z","EdgeResponseBytes":363,"EdgeResponseStatus":200,"EdgeStartTimestamp":"2022-01-25T17:23:06Z","RayID":"6d332fffe9c4fc81","sampleInterval":1}</code></pre>
            
    <div>
      <h2>The Scenario</h2>
      <a href="#the-scenario">
        
      </a>
    </div>
    <p>Now that you are able to create a new Instant Logs session let’s give it a purpose! Say you just recently deployed a new firewall rule blocking users from downloading a specific asset that is only available to users in Canada. For the purpose of this example, the asset is available at the path <code>/canadians-only</code>.</p>
    <div>
      <h3>Specifying Fields</h3>
      <a href="#specifying-fields">
        
      </a>
    </div>
    <p>In order to see what firewall actions (if any) were taken, we need to make sure that we include <code>ClientRequestCountry</code>, <code>​​FirewallMatchesActions</code> and <code>FirewallMatchesRuleIDs</code> fields when creating our session.</p><p>Additionally, any field available in our HTTP request dataset is usable by Instant Logs. You can view the entire list of HTTP Request fields <a href="https://developers.cloudflare.com/logs/reference/log-fields/zone/http_requests">on our developer docs</a>.</p>
    <div>
      <h3>Choosing a Sample Rate</h3>
      <a href="#choosing-a-sample-rate">
        
      </a>
    </div>
    <p>Instant Logs users also have the ability to choose a sample rate. The <code>sample</code> parameter is the inverse probability of selecting a log. This means that <code>"sample": 1</code> is 100% of records, <code>"sample": 10</code> is 10% and so on.</p><p>Going back to our example of validating that our newly deployed firewall rule is working as expected, in this case, we are choosing not to sample the data by setting <code>"sample": 1</code>.</p><p>Please note that Instant Logs has a maximum data rate supported. For high volume domains, we sample server side as indicated in the "sampleInterval" parameter returned in the logs. For example, "sampleInterval": 10 indicates this log message is just one out of 10 logs received.</p>
    <div>
      <h3>Defining the Filters</h3>
      <a href="#defining-the-filters">
        
      </a>
    </div>
    <p>Since we are only interested in requests with the path of <code>/canadians-only</code>, we can use filters to remove any logs that do not match that specific path. The filters consist of three parts: <code>key</code>, <code>operator</code> and <code>value</code>. The <code>key</code> can be any field specified in the <code>"fields": ""</code> list when creating the session. The complete list of supported operators can be found on our <a href="https://developers.cloudflare.com/logs/instant-logs">Instant Logs documentation</a>.</p><p>To only get the logs of requests destined to <code>/canadians-only</code>, we can specify the following filter:</p>
            <pre><code>{
  "filter": "{\"where\":{\"and\":[{\"key\":\"ClientRequestPath\",\"operator\":\"eq\",\"value\":\"/canadians-only\"}]}}"
}</code></pre>
            
    <div>
      <h2>Creating an Instant Logs Session: Canadians Only</h2>
      <a href="#creating-an-instant-logs-session-canadians-only">
        
      </a>
    </div>
    <p>Using the information above, we can now craft the request for our custom Instant Logs session.</p>
            <pre><code>curl -X POST 'https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/logpush/edge/jobs' \
-H 'X-Auth-Key: &lt;KEY&gt;' \
-H 'X-Auth-Email: &lt;EMAIL&gt;' \
-H 'Content-Type: application/json' \
--data-raw '{
  "fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,ClientCountry,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID,FirewallMatchesActions,FirewallMatchesRuleIDs",
  "sample": 1,
  "kind": "instant-logs",
  "filter": "{\"where\":{\"and\":[{\"key\":\"ClientRequestPath\",\"operator\":\"eq\",\"value\":\"/canadians-only\"}]}}"
}'</code></pre>
            
    <div>
      <h3>Angle Grinder</h3>
      <a href="#angle-grinder">
        
      </a>
    </div>
    <p>Now that we have a connection to our WebSocket and are receiving logs that match the request path <code>/canadians-only</code>, we can start slicing and dicing the logs to see that the rule is working as expected. A handy tool to use for this is <a href="https://github.com/rcoh/angle-grinder">Angle Grinder</a>. Angle Grinder lets you apply filtering, transformations and aggregations on stdin with first class JSON support. For example, to get the number of visitors from each country we can sum the number of events by the <code>ClientCountry</code> field.</p>
            <pre><code>websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2 | agrind '* | json | sum(sampleInterval) by ClientCountry'
ClientCountry    	_sum
---------------------------------
pt               	4
fr               	3
us               	3</code></pre>
            <p>Using Angle Grinder, we can create a query to count the firewall actions by each country.</p>
            <pre><code>websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2 |  agrind '* | json | sum(sampleInterval) by ClientCountry,FirewallMatchesActions'
ClientCountry        FirewallMatchesActions        _sum
---------------------------------------------------------------
ca                   []                            5
us                   [block]                       1</code></pre>
            <p>Looks like our newly deployed firewall rule is working :)</p><p>Happy Logging!</p> ]]></content:encoded>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[Logs]]></category>
            <guid isPermaLink="false">5upQVQrIIaXHco5X9VKRGb</guid>
            <dc:creator>Cole MacKenzie</dc:creator>
        </item>
        <item>
            <title><![CDATA[Learn more about Workers Sites at Austin & San Francisco Meetups]]></title>
            <link>https://blog.cloudflare.com/learn-more-about-workers-sites-at-austin-san-francisco-meetups/</link>
            <pubDate>Wed, 02 Oct 2019 01:00:10 GMT</pubDate>
            <description><![CDATA[ Last Friday, at the end of Cloudflare’s 9th birthday week, we announced Workers Sites. Now, using the Wrangler CLI, you can deploy entire websites directly to the Cloudflare Network using Cloudflare Workers and Workers KV. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Last Friday, at the end of Cloudflare’s 9th <a href="/birthday-week-2019-wrap-up/">birthday week</a>, we announced <a href="/extending-the-workers-platform/">Workers Sites</a>.</p><p>Now, using the Wrangler CLI, you can deploy entire websites directly to the Cloudflare Network using <a href="https://workers.cloudflare.com/">Cloudflare Workers</a> and Workers KV. If you can statically generate the assets for your site, think create-react-app, Jekyll, or even the WP2Static plugin, you can deploy it to our global network, which spans 194 cities in more than 90 countries.</p><p>If you’d like to learn more about how it was built, you can read more about this in the <a href="/extending-the-workers-platform/">technical blog post</a>. Additionally, I wanted to give you an opportunity to meet with some of the developers who contributed to this product and hear directly from them about their process, potential use cases, and what it took to build.</p><p>Check out these events. If you’re based in Austin or San Francisco (more cities coming soon!), join us on-site. If you’re based somewhere else, you can watch the recording of the events afterwards.</p><p>Growing Dev Platforms at Scale &amp; Deploying Static Websites</p><hr />
    <div>
      <h3>Talk 1: Inspiring with Content: How to Grow Developer Platforms at Scale</h3>
      <a href="#talk-1-inspiring-with-content-how-to-grow-developer-platforms-at-scale">
        
      </a>
    </div>
    <p>Serverless platforms like Cloudflare Workers provide benefits like scalability, high performance, and lower costs. However, when talking to developers, one of the most common reactions is, "this sounds interesting, but what do I build with it?"</p><p>In this talk, we’ll cover how at Cloudflare we’ve been able to answer this question at scale with Workers Sites. We’ll go over why this product exists and how the implementation leads to some unintended discoveries.</p><p><b>Speaker Bio</b>:<a href="https://twitter.com/miss_vee22">Victoria Bernard</a> is a full-stack, product-minded engineer focused on Cloudflare Workers Developer Experience. An engineer who started a career working at large firms in hardware sales and moved throughout Cloudflare from support to product and to development. Passionate about building products that make developer lives easier and more productive.</p>
    <div>
      <h3>Talk 2:  Extending a Serverless Platform: How to Fake a File System…and Get Away With It</h3>
      <a href="#talk-2-extending-a-serverless-platform-how-to-fake-a-file-system-and-get-away-with-it">
        
      </a>
    </div>
    <p>When building a platform for developers, you can’t anticipate every use case. So, how do you build new functionality into a platform in a sustainable way, and inspire others to do the same?</p><p>Let’s talk about how we took a globally distributed serverless platform (Cloudflare Workers) and key-value store (Workers KV) intended to store short-lived data and turned them into a way to easily deploy static websites. It wasn’t a straightforward journey, but join as we overcome roadblocks and learn a few lessons along the way.</p><p><b>Speaker Bio:</b><a href="https://twitter.com/ashleymichaldev">Ashley Lewis</a> headed the development of the features that became Workers Sites. She's process and collaboration oriented and focused on user experience first at every level of the stack. Ashley proudly tops the leaderboard for most LOC deleted.</p><p><b>Agenda</b>:</p><ul><li><p>6:00pm - Doors open</p></li><li><p>6:30pm - Talk 1: Inspiring with Content: How to Grow Developer Platforms at Scale</p></li><li><p>7:00pm - Talk 2:  Extending a Serverless Platform: How to Fake a File System…and Get Away With It</p></li><li><p>7:30pm - Networking over food and drinks</p></li><li><p>8:00pm - Event conclusion</p></li></ul>
    <div>
      <h3>Austin, Texas Meetup</h3>
      <a href="#austin-texas-meetup">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1gxlJEQ4Q6yT0QJcAeGyV0/f252f8d4902f9010d147cf1ecc9c762f/Austin-Serverless-Meetup-_2x.png" />
            
            </figure><ul><li><p><b>DATE/TIME</b> - October 3, 6:00pm-8:00pm</p></li><li><p><b>LOCATION</b>: <a href="https://goo.gl/maps/K2scWSiF4NzGXU7CA">Cloudflare Austin</a></p></li></ul><p><a href="https://www.meetup.com/Real-World-Serverless-Austin/events/265007453/">Register Here »</a></p>
    <div>
      <h3>San Francisco, California Meetup</h3>
      <a href="#san-francisco-california-meetup">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5nERQrfsBd0TwvmDwAWR5x/5d6b7d200e65c19d15803814dacdbb5f/San-Francisco-Serverless-Meetup_2x-1.png" />
            
            </figure><ul><li><p><b>DATE/TIME -</b> October 14, 6:00pm-8:00pm</p></li><li><p><b>LOCATION</b> - <a href="https://g.page/cloudflare-hq?share">Cloudflare San Francisco</a></p></li></ul><p><a href="https://www.meetup.com/Real-World-Serverless-San-Francisco/events/265104055/">Register Here »</a></p><p>While you’re at it, check out our monthly developer newsletter: <a href="/serverlist/">The Serverlist</a></p><hr /><p><i>Have you built something interesting with Workers? Let us know</i> <a href="http://twitter.com/@CloudflareDev"><i>@CloudflareDev</i></a><i>!</i></p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Meetups]]></category>
            <category><![CDATA[Austin]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">3CwD4udUdxIxIT3h6rgVsL</guid>
            <dc:creator>Andrew Fitch</dc:creator>
        </item>
        <item>
            <title><![CDATA[Live Preview: Build and Test Workers Faster with Wrangler CLI 1.2.0]]></title>
            <link>https://blog.cloudflare.com/live-preview-build-and-test-workers-faster-with-wrangler-cli-1-2-0/</link>
            <pubDate>Mon, 19 Aug 2019 22:36:00 GMT</pubDate>
            <description><![CDATA[ As part of my internship on the Workers Developer Experience team, I set out to polish the Wrangler CLI for Cloudflare Workers. If you're not familiar with Workers, the premise is quite simple: Write a bit of Javascript that takes in an HTTP request, does some processing, and spits out a response.  ]]></description>
            <content:encoded><![CDATA[ <p>As part of my internship on the Workers Developer Experience team, I set out to polish the <a href="https://github.com/cloudflare/wrangler">Wrangler CLI</a> for <a href="https://workers.cloudflare.com/">Cloudflare Workers</a>. If you're not familiar with Workers, the premise is quite simple: Write a bit of Javascript that takes in an HTTP request, does some processing, and spits out a response. The magic lies in where your Workers scripts run: on Cloudflare's edge network, which spans 193 cities in more than 90 countries. Workers can be used for nearly anything from configuring Cloudflare caching behavior to building entire serverless web applications. And, you don't have to worry about operations at <i>all.</i></p><p>I was excited to focus on Wrangler, because Wrangler aims to make developing and publishing Workers projects a pleasant experience for everyone, whether you're a solo dev working on the next big thing, or an engineer at a Fortune 100 enterprise. The whole point of serverless is about reducing friction, and Wrangler reflects that ethos.</p><p>However, when I started at Cloudflare in early June, some parts of the development experience still needed some love. While working on a new <a href="https://workers.cloudflare.com/docs/tutorials/build-a-rustwasm-function/">WASM tutorial</a> for the Workers documentation, I noticed a storm brewing in my browser…</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1weM15yKROpJCcZVqofQXu/f304b0cca5b5cd12baa4128819c6780f/image1.gif" />
            
            </figure><p>Wrangler lets you test your Workers project with a subcommand called <code>wrangler preview</code>, and every time I called it to test a new change it opened a new tab. Fast iteration is the most crucial part of a good developer experience, and while the preview was fast, things were getting messy. I was fighting my tooling, having to keep track of the latest preview tab every time I wanted to test a new change. I knew that if I was annoyed about this, others would be too.</p><p>So, I thought about what our customers wanted: similarity with tooling that they already used. I set out to create an experience inspired by `webpack-dev-server` and other similar watch-and-build tools, where you would have a single tab that would refresh live with your latest changes. However, I knew that getting changes into the Workers runtime to achieve this goal would be a tall order for week 2 of my internship, so I started thinking about solutions to send updates directly to the previewer.</p><p>Wrangler is written in <a href="https://www.rust-lang.org/">Rust</a>, so I was able to utilize the <a href="https://crates.io/">crates.io</a> ecosystem while developing this feature. I used the <a href="https://crates.io/crates/notify">notify</a> crate, which provides a cross-platform abstraction layer over the various file system event APIs provided by major OSes. However, there are some gotchas when implementing a file watcher that triggers a build and upload: you can’t simply trigger a build after every filesystem event, as a single file save can emit several events in quick succession depending on which editor you use! To prevent wasteful builds, I implemented a cooldown period, which only triggers the build process when no new file system events have been detected for at least 2 seconds. Rust’s rich standard library makes implementing concurrent behaviors like this very elegant:</p>
            <pre><code>/* rx.recv_timeout returns Ok if there was an event on the rx channel
 * or Err if the cooldown period has passed. The while let Ok(_) syntax
 * will end the loop if the cooldown period has ended, or restart the cooldown period if there was an event on the rx channel
 */
while let Ok(_) = rx.recv_timeout(cooldown) {
  message::working("Detected change during cooldown...");
}</code></pre>
            <p>Another challenge was handling communication with the previewer. I settled on an unconventional application of WebSockets, creating one to localhost to allow for a browser application to communicate with the Wrangler CLI running on the local machine. I coordinated with the Workers UI team to get my WebSocket client added to the preview UI, and with the security team to pass a security review for the feature, to make sure script contents were properly protected from exposure.</p><p>This was the result:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4BJCQTvxxCvz4yvGyc3IQs/d7e1ceed920b50caa1b240b934dc8b44/out_opt--1-.gif" />
            
            </figure><p>This is what Developer Experience is all about. You should feel like ??‍♀️??‍♂️ when using Wrangler, not like ?. <i>If this isn't the case, </i><a href="https://github.com/cloudflare/wrangler/issues/new/choose"><i>we want to hear about it</i></a><i>.</i></p><p>Live Preview was shipped in the <a href="https://github.com/cloudflare/wrangler/releases/tag/v1.2.0">1.2.0 release</a> of <a href="https://github.com/cloudflare/wrangler">Wrangler</a>, exposed under <code>wrangler preview --watch</code>. It works for all Wrangler projects, even ones that use WebAssembly.</p><p>And to the Workers Developer Experience team, Dubs, Ashley, Avery, Gabbi, Kristian, Sven, and Victoria: thank you. Y'all are motivated, talented, and I genuinely had fun every day this summer.</p> ]]></content:encoded>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">62c8xwr8Lc0wLybQfNLvnR</guid>
            <dc:creator>Matt Alonso</dc:creator>
        </item>
        <item>
            <title><![CDATA[Eating Dogfood at Scale: How We Build Serverless Apps with Workers]]></title>
            <link>https://blog.cloudflare.com/building-serverless-apps-with-workers/</link>
            <pubDate>Fri, 19 Apr 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ You’ve had a chance to build a Cloudflare Worker. You’ve tried KV Storage and have a great use case for your Worker. You’ve even demonstrated the usefulness to your product or organization.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>You’ve had a chance to build a <a href="https://developers.cloudflare.com/workers/about/">Cloudflare Worker</a>. You’ve tried <a href="https://developers.cloudflare.com/workers/kv/">KV Storage</a> and have a great use case for your Worker. You’ve even demonstrated the usefulness to your product or organization. Now you need to go from writing a single file in the Cloudflare Dashboard UI Editor to source controlled code with multiple environments deployed using your favorite CI tool.</p><p>Fortunately, we have a powerful and flexible <a href="https://developers.cloudflare.com/workers/api/">API</a> for managing your workers. You can customize your deployment to your heart’s content. Our blog has already featured many things made possible by that API:</p><ul><li><p><a href="/introducing-wrangler-cli/">The Wrangler CLI</a></p></li><li><p><a href="/a-ci/">CI/CD Pipeline</a></p></li><li><p><a href="/deploying-workers-with-github-actions-serverless/">Github Actions</a></p></li><li><p><a href="/create-cloudflare-worker-bootstrap-your-cloudflare-worker/">Worker bootstrap template</a></p></li></ul><p>These tools make deployments easier to configure, but it still takes time to manage. The <a href="https://serverless.com/">Serverless Framework</a> <a href="https://serverless.com/plugins/serverless-cloudflare-workers/">Cloudflare Workers plugin</a> removes that deployment overhead so you can spend more time working on your application and less on your deployment.</p>
    <div>
      <h3>Focus on your application</h3>
      <a href="#focus-on-your-application">
        
      </a>
    </div>
    <p>Here at Cloudflare, we’ve been working to rebuild our Access product to run entirely on Workers. The move will allow Access to take advantage of the resiliency, performance, and flexibility of Workers. We’ll publish a more detailed post about that migration once complete, but the experience required that we retool some of our process to match or existing development experience as much as possible.</p><p>To us this meant:</p><ul><li><p>Git</p></li><li><p>Easily deploy</p></li><li><p>Different environments</p></li><li><p>Unit Testing</p></li><li><p>CI Integration</p></li><li><p>Typescript/Multiple Files</p></li><li><p>Everything Must Be Automated</p></li></ul><p>The Cloudflare Access team looked at three options for automating all of these tools in our pipeline. All of the options will work and could be right for you, but custom scripting can be a chore to maintain and Terraform lacked some extensibility.</p><ol><li><p>Custom Scripting</p></li><li><p><a href="https://www.terraform.io/docs/providers/cloudflare/index.html">Terraform</a></p></li><li><p>Serverless Framework</p></li></ol><p>We decided on the Serverless Framework. Serverless Framework provided a tool to mirror our existing process as closely as possible without too much DevOps overhead. Serverless is extremely simple and doesn’t interfere with the application code. You can get a project set up and deployed in seconds. It’s obviously less work than writing your own custom management scripts. But it also requires less boiler plate than Terraform because the Serverless Framework is designed for the “serverless” niche. However, if you are already using Terraform to manage other Cloudflare products, Terraform might be the best fit.</p>
    <div>
      <h3>Walkthrough</h3>
      <a href="#walkthrough">
        
      </a>
    </div>
    <p>Everything for the project happens in a YAML file called serverless.yml. Let’s go through the features of the configuration file.</p><p>To get started, we need to install serverless from npm and generate a new project.</p>
            <pre><code>npm install serverless -g
serverless create --template cloudflare-workers --path myproject
cd myproject
npm install</code></pre>
            <p>If you are an enterprise client, you want to use the cloudflare-workers-enterprise template as it will set up more than one worker (but don’t worry, you can add more to any template). Also, I’ll touch on this later, but if you want to write your workers in Rust, use the cloudflare-workers-rust template.</p><p>You should now have a project that feels familiar, ready to be added to your favorite source control. In the project should be a serverless.yml file like the following.</p>
            <pre><code>service:
    name: hello-world

provider:
  name: cloudflare
  config:
    accountId: CLOUDFLARE_ACCOUNT_ID
    zoneId: CLOUDFLARE_ZONE_ID

plugins:
  - serverless-cloudflare-workers

functions:
  hello:
    name: hello
    script: helloWorld  # there must be a file called helloWorld.js
    events:
      - http:
          url: example.com/hello/*
          method: GET
          headers:
            foo: bar
            x-client-data: value</code></pre>
            <p>The service block simply contains the name of your service. This will be used in your Worker script names if you do not overwrite them.</p><p>Under provider, name must be ‘cloudflare’  and you need to add your account and zone IDs. You can find them in the Cloudflare Dashboard.</p><p>The plugins section adds the Cloudflare specific code.</p><p>Now for the good part: functions. Each block under functions is a Worker script.</p><p><b>name</b>: (optional) If left blank it will be STAGE-service.name-script.identifier. If I removed name from this file and deployed in production stage, the script would be named production-hello-world-hello.</p><p><b>script</b>: the relative path to the javascript file with the worker script. I like to organize mine in a folder called handlers.</p><p><b>events</b>: Currently Workers only support http events. We call these routes. The example provided says that GET <a href="https://example.com/hello/">https://example.com/hello/</a> will  cause this worker to execute. The headers block is for testing invocations.</p><p>At this point you can deploy your worker!</p>
            <pre><code>CLOUDFLARE_AUTH_EMAIL=you@yourdomain.com CLOUDFLARE_AUTH_KEY=XXXXXXXX serverless deploy</code></pre>
            <p>This is very easy to deploy, but it doesn’t address our requirements. Luckily, there’s just a few simple modifications to make.</p>
    <div>
      <h3>Maturing our YAML File</h3>
      <a href="#maturing-our-yaml-file">
        
      </a>
    </div>
    <p>Here’s a more complex YAML file.</p>
            <pre><code>service:
  name: hello-world

package:
  exclude:
    - node_modules/**
  excludeDevDependencies: false

custom:
  defaultStage: development
  deployVars: ${file(./config/deploy.${self:provider.stage}.yml)}

kv: &amp;kv
  - variable: MYUSERS
    namespace: users

provider:
  name: cloudflare
  stage: ${opt:stage, self:custom.defaultStage}
  config:
    accountId: ${env:CLOUDFLARE_ACCOUNT_ID}
    zoneId: ${env:CLOUDFLARE_ZONE_ID}

plugins:
  - serverless-cloudflare-workers

functions:
  hello:
    name: ${self:provider.stage}-hello
    script: handlers/hello
    webpack: true
    environment:
      MY_ENV_VAR: ${self:custom.deployVars.env_var_value}
      SENTRY_KEY: ${self:custom.deployVars.sentry_key}
    resources: 
      kv: *kv
    events:
      - http:
          url: "${self:custom.deployVars.SUBDOMAIN}.mydomain.com/hello"
          method: GET
      - http:
          url: "${self:custom.deployVars.SUBDOMAIN}.mydomain.com/alsohello*"
          method: GET</code></pre>
            <p>We can add a custom section where we can put custom variables to use later in the file.</p><p><b>defaultStage</b>: We set this to development so that forgetting to pass a stage doesn’t trigger a production deploy. Combined with the <b>stage</b> option under provider we can set the stage for deployment.</p><p><b>deployVars</b>: We use this custom variable to load another YAML file dependent on the stage. This lets us have different values for different stages. In development, this line loads the file <code>./config/deploy.development.yml</code>. Here’s an example file:</p>
            <pre><code>env_var_value: true
sentry_key: XXXXX
SUBDOMAIN: dev</code></pre>
            <p><b>kv</b>: Here we are showing off a feature of YAML. If you assign a name to a block using the ‘&amp;’, you can use it later as a YAML variable. This is very handy in a multi script account. We could have named this variable anything, but we are naming it kv since it holds our Workers Key Value storage settings to be used in our function below.</p><p>Inside of the <b>kv</b> block we're creating a namespace and binding it to a variable available in your Worker. It will ensure that the namespace “users” exists and is bound to MYUSERS.</p>
            <pre><code>kv: &amp;kv
  - variable: MYUSERS
    namespace: users</code></pre>
            <p><b>provider</b>: The only new part of the provider block is <b>stage</b>.</p>
            <pre><code>stage: ${opt:stage, self:custom.defaultStage}</code></pre>
            <p>This line sets stage to either the command line option or custom.defaultStage if opt:stage is blank. When we deploy, we pass —stage=production to serverless deploy.</p><p>Now under our function we have added webpack, resources, and environment.</p><p><b>webpack</b>: If set to true, will simply bundle each handler into a single file for deployment. It will also take a string representing a path to a webpack config file so you can customize it. This is how we add Typescript support to our projects.</p><p><b>resources</b>: This block is used to automate resource creation. In resources we're linking back to the kv block we created earlier.</p><p><i>Side note: If you would like to include WASM bindings in your project, it can be done in a very similar way to how we included Workers KV. For more information on WASM, see the </i><a href="https://serverless.com/plugins/serverless-cloudflare-workers/"><i>documentation</i></a><i>.</i></p><p><b>environment</b>: This is the butter for the bread that is managing configuration for different stages. Here we can specify values to bind to variables to use in worker scripts. Combined with YAML magic, we can store our values in the aforementioned config files so that we deploy different values in different stages. With environments, we can easily tie into our CI tool. The CI tool has our deploy.production.yml. We simply run the following command from within our CI.</p>
            <pre><code>sls deploy --stage=production</code></pre>
            <p>Finally, I added a route to demonstrate that a script can be executed on multiple routes.</p><p>At this point I’ve covered (or hinted) at everything on our original list except Unit Testing. There are a few ways to do this.</p><p>We have a previous blog post about <a href="/unit-testing-worker-functions/">Unit Testing</a> that covers using <a href="https://github.com/dollarshaveclub/cloudworker">cloud worker</a>, a great tool built by <a href="https://www.dollarshaveclub.com/">Dollar Shave Club</a>.</p><p>My team opted to use the classic node frameworks mocha and sinon. Because we are using Typescript, we can build for node or build for v8. You can also make mocha work for non-typescript projects if you use an <a href="https://nodejs.org/api/esm.html">experimental feature that adds import/export support to node</a>.</p>
            <pre><code>--experimental-modules</code></pre>
            <p>We’re excited about moving more and more of our services to Cloudflare Workers, and the Serverless Framework makes that easier to do. If you’d like to learn even more or get involved with the project, see us on <a href="https://github.com/cloudflare/serverless-cloudflare-workers">github.com</a>. For additional information on using Serverless Framework with Cloudflare Workers, check out our <a href="https://developers.cloudflare.com/workers/deploying-workers/serverless/">documentation on the Serverless Framework</a>.</p> ]]></content:encoded>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[API]]></category>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[GitHub]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">40cVOSqV3lXK8azULKCab7</guid>
            <dc:creator>Jonathan Spies</dc:creator>
        </item>
        <item>
            <title><![CDATA[? The Wrangler CLI: Deploying Rust with WASM on Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/introducing-wrangler-cli/</link>
            <pubDate>Thu, 28 Mar 2019 16:08:45 GMT</pubDate>
            <description><![CDATA[ Today, we're open sourcing and announcing wrangler, a CLI tool for building, previewing, and publishing Rust and WebAssembly Cloudflare Workers. If that sounds like some word salad to you, that's a reasonable reaction. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Wrangler is a CLI tool for building Rust WebAssembly Workers</p><p>Today, we're open sourcing and announcing <code>wrangler</code>, a CLI tool for building, previewing, and publishing Rust and WebAssembly Cloudflare Workers.</p><p>If that sounds like some word salad to you, that's a reasonable reaction. All three of the technologies involved are relatively new and upcoming: WebAssembly, Rust, and Cloudflare Workers.</p>
    <div>
      <h3>Why WebAssembly?</h3>
      <a href="#why-webassembly">
        
      </a>
    </div>
    <p>Cloudflare's mission is to help build a better Internet. We see Workers as an extension of the already incredibly powerful Web Platform, where JavaScript has allowed users to go from building small bits of interactivity, to building full applications. Node.js first extended this from the client to the server- unifying web application development around a single language – JavaScript. By choosing to use V8 isolates (the technology that powers both Node.js and the most popular browser, Chrome), we sought to make its Workers product a fully compatible, new platform for the Web, eliding the distinction between server and client. By leveraging its large global network of servers, Workers allows users to run code as close as possible to end users, eliminating the latency associated server-side logic or large client-side bundles.</p><p>But not everyone wants to write JavaScript, and JavaScript is not well suited to express every application. WebAssembly emerged in 2017 as a way to further extend the Web Platform to applications, such as games and other high resource intensive programs, that were previously excluded by the limitations of JavaScript.</p><p>V8 isolates give us both JavaScript and WebAssembly. This means that you can leverage the prototyping power and extensive ecosystem of JavaScript, alongside the power of WebAssembly, which in addition to fast, predictable, performance, also opens up the wealth of libraries written in languages that can target WebAssembly, like C, C++, and Rust.</p><p>WebAssembly on Workers eliminates trade-offs that were originally considered irresolvable: low-latency, high-performing, and Web Platform compatible- pick three.</p>
    <div>
      <h3>Why Rust?</h3>
      <a href="#why-rust">
        
      </a>
    </div>
    <p>Rust is a relatively new programming language with the goal of "empowering everyone to build reliable and efficient software". It's a systems level language that offers its users a high amount of control, while still seeking to offer an ergonomic, friendly and modern development experience.</p><p>The Rust-WebAssembly Working Group made incredible efforts last year to build out a suite of developer tools for WebAssembly. At Cloudflare, we're excited to support those efforts with paid developer hours and leverage those efforts to empower our users to start harnessing the power of WebAssembly on Workers now.</p><p>There are several other toolchains including Emscripten (C, C++) and AssemblyScript (TypeScript) that we're eager to support in the future. Rust is just the beginning (but we think it's a pretty great place to start!).</p>
    <div>
      <h3>Why now?</h3>
      <a href="#why-now">
        
      </a>
    </div>
    <p>When developing new, highly technical, products, it's easy to get caught up in the promise and vision- often to the detriment of getting the technology into the hands of the folks who will be using it every day in the future.</p><p>We want to broaden the community that has access at the early stages of this technology- who can bring their valuable perspectives and experience, and help us shape the future of these tools.</p><p>The first step to accomplishing that is building the tools that can <i>enable</i> folks to engage with the new platform. <code>wrangler</code> is a that enabling tool. It's just enough to unblock users who were previously unable to interact with the platform because there was no paved path.</p><p>We don't plan to stop here. Folks will rightly note that there are some critical developer workflow steps that are missing from <code>wrangler</code>: linting, testing, benchmarking, and size profiling are a few that come to mind. We've got some big plans and we're excited to build out more, but we're eager to release this now to enable <i>more</i> folks to participate in the process. The best way to know what developers need is to ask and listen- by creating and open sourcing <code>wrangler</code> in such an early phase we're hoping to shorten the feedback cycle between product and user- and build the <i>right</i> thing, <i>faster</i>.</p><p>You can install <code>wrangler</code> using <code>cargo</code>:</p>
            <pre><code>cargo install wrangler</code></pre>
            <p>To get started, head on over to the <a href="https://developers.cloudflare.com/workers/cli-wrangler">Cloudflare docs</a> and follow the <a href="https://developers.cloudflare.com/workers/cli-wrangler/install-update">tutorial</a>. You'll build and preview a Cloudflare Worker that uses Rust compiled to WebAssembly to parse <a href="https://blog.cloudflare.com/markdown-for-agents/">Markdown</a>.</p><p>Don't stop there though. Please check out <a href="https://github.com/cloudflare/wrangler">the repo</a>, <a href="https://github.com/cloudflare/wrangler/issues">file some issues</a>, build project templates, and write about your experience- we want to hear from you.</p><p>We're really excited to see what y'all build!</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[WebAssembly]]></category>
            <category><![CDATA[Rust]]></category>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[Wrangler]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">36wNfaZBn3VBQ13FPMMsJW</guid>
            <dc:creator>Ashley Williams</dc:creator>
        </item>
    </channel>
</rss>