
<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>Wed, 15 Apr 2026 04:49:50 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Bringing Node.js HTTP servers to Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/bringing-node-js-http-servers-to-cloudflare-workers/</link>
            <pubDate>Mon, 08 Sep 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ We've implemented the node:http client and server APIs in Cloudflare Workers, allowing developers to migrate existing Node.js applications with minimal code changes. ]]></description>
            <content:encoded><![CDATA[ <p>We’re making it easier to run your Node.js applications on <a href="https://www.cloudflare.com/developer-platform/products/workers/"><u>Cloudflare Workers </u></a>by adding support for the <code>node:http</code> client and server APIs. This significant addition brings familiar Node.js HTTP interfaces to the edge, enabling you to deploy existing Express.js, Koa, and other Node.js applications globally with zero cold starts, automatic scaling, and significantly lower latency for your users — all without rewriting your codebase. Whether you're looking to migrate legacy applications to a modern serverless platform or build new ones using the APIs you already know, you can now leverage Workers' global network while maintaining your existing development patterns and frameworks.</p>
    <div>
      <h2>The Challenge: Node.js-style HTTP in a Serverless Environment</h2>
      <a href="#the-challenge-node-js-style-http-in-a-serverless-environment">
        
      </a>
    </div>
    <p>Cloudflare Workers operate in a unique <a href="https://www.cloudflare.com/learning/serverless/what-is-serverless/"><u>serverless</u></a> environment where direct tcp connection isn't available. Instead, all networking operations are fully managed by specialized services outside the Workers runtime itself — systems like our <a href="https://blog.cloudflare.com/introducing-oxy/"><u>Open Egress Router (OER)</u></a> and <a href="https://github.com/cloudflare/pingora"><u>Pingora</u></a> that handle connection pooling, keeping connections warm, managing egress IPs, and all the complex networking details. This means as a developer, you don't need to worry about TLS negotiation, connection management, or network optimization — it's all handled for you automatically.</p><p>This fully-managed approach is actually why we can't support certain Node.js APIs — these networking decisions are handled at the system level for performance and security. While this makes Workers different from traditional Node.js environments, it also makes them better for serverless computing — you get enterprise-grade networking without the complexity.</p><p>This fundamental difference required us to rethink how HTTP APIs work at the edge while maintaining compatibility with existing Node.js code patterns.</p><p>Our Solution: we've implemented the core `node:http` APIs by building on top of the web-standard technologies that Workers already excel at. Here's how it works:</p>
    <div>
      <h3>HTTP Client APIs</h3>
      <a href="#http-client-apis">
        
      </a>
    </div>
    <p>The <code>node:http</code> client implementation includes the essential APIs you're familiar with:</p><ul><li><p><code>http.get()</code> - For simple GET requests</p></li><li><p><code>http.request()</code> - For full control over HTTP requests</p></li></ul><p>Our implementations of these APIs are built on top of the standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"><code><u>fetch()</u></code></a> API that Workers use natively, providing excellent performance while maintaining Node.js compatibility.</p>
            <pre><code>import http from 'node:http';

export default {
  async fetch(request) {
    // Use familiar Node.js HTTP client APIs
    const { promise, resolve, reject } = Promise.withResolvers();

    const req = http.get('https://api.example.com/data', (res) =&gt; {
      let data = '';
      res.on('data', chunk =&gt; data += chunk);
      res.on('end', () =&gt; {
        resolve(new Response(data, {
          headers: { 'Content-Type': 'application/json' }
        }));
      });
    });

    req.on('error', reject);

    return promise;
  }
};</code></pre>
            
    <div>
      <h3>What's Supported</h3>
      <a href="#whats-supported">
        
      </a>
    </div>
    <ul><li><p>Standard HTTP methods (GET, POST, PUT, DELETE, etc.)</p></li><li><p>Request and response headers</p></li><li><p>Request and response bodies</p></li><li><p>Streaming responses</p></li><li><p>Basic authentication</p></li></ul>
    <div>
      <h3>Current Limitations</h3>
      <a href="#current-limitations">
        
      </a>
    </div>
    <ul><li><p>The <a href="https://nodejs.org/api/http.html#class-httpagent"><code><u>Agent</u></code></a> API is provided but operates as a no-op.</p></li><li><p><a href="https://nodejs.org/docs/v22.19.0/api/http.html#responseaddtrailersheaders"><u>Trailers</u></a>, <a href="https://nodejs.org/docs/v22.19.0/api/http.html#responsewriteearlyhintshints-callback"><u>early hints</u></a>, and <a href="https://nodejs.org/docs/v22.19.0/api/http.html#event-continue"><u>1xx responses</u></a> are not supported.</p></li><li><p>TLS-specific options are not supported (Workers handle TLS automatically).</p></li></ul>
    <div>
      <h2>HTTP Server APIs</h2>
      <a href="#http-server-apis">
        
      </a>
    </div>
    <p>The server-side implementation is where things get particularly interesting. Since Workers can't create traditional TCP servers listening on specific ports, we've created a bridge system that connects Node.js-style servers to the Workers request handling model.</p><p>When you create an HTTP server and call <code>listen(port)</code>, instead of opening a TCP socket, the server is registered in an internal table within your Worker. This internal table acts as a bridge between http.createServer executions and the incoming fetch requests using the port number as the identifier. 

You then use one of two methods to bridge incoming Worker requests to your Node.js-style server.</p>
    <div>
      <h3>Manual Integration with <code>handleAsNodeRequest</code></h3>
      <a href="#manual-integration-with-handleasnoderequest">
        
      </a>
    </div>
    <p>This approach gives you the flexibility to integrate Node.js HTTP servers with other Worker features, and allows you to have multiple handlers in your default <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/"><u>entrypoint</u></a> such as <code>fetch</code>, <code>scheduled</code>, <code>queue</code>, etc.</p>
            <pre><code>import { handleAsNodeRequest } from 'cloudflare:node';
import { createServer } from 'node:http';

// Create a traditional Node.js HTTP server
const server = createServer((req, res) =&gt; {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello from Node.js HTTP server!');
});

// Register the server (doesn't actually bind to port 8080)
server.listen(8080);

// Bridge from Workers fetch handler to Node.js server
export default {
  async fetch(request) {
    // You can add custom logic here before forwarding
    if (request.url.includes('/admin')) {
      return new Response('Admin access', { status: 403 });
    }

    // Forward to the Node.js server
    return handleAsNodeRequest(8080, request);
  },
  async queue(batch, env, ctx) {
    for (const msg of batch.messages) {
      msg.retry();
    }
  },
  async scheduled(controller, env, ctx) {
    ctx.waitUntil(doSomeTaskOnSchedule(controller));
  },
};</code></pre>
            <p>This approach is perfect when you need to:</p><ul><li><p>Integrate with other Workers features like <a href="https://www.cloudflare.com/developer-platform/products/workers-kv/"><u>KV</u></a>, <a href="https://www.cloudflare.com/developer-platform/products/durable-objects/"><u>Durable Objects</u></a>, or <a href="https://www.cloudflare.com/developer-platform/products/r2/"><u>R2</u></a></p></li><li><p>Handle some routes differently while delegating others to the Node.js server</p></li><li><p>Apply custom middleware or request processing</p></li></ul>
    <div>
      <h3>Automatic Integration with <code>httpServerHandler</code></h3>
      <a href="#automatic-integration-with-httpserverhandler">
        
      </a>
    </div>
    <p>For use cases where you want to integrate a Node.js HTTP server without any additional features or complexity, you can use the `httpServerHandler` function. This function automatically handles the integration for you. This solution is ideal for applications that don’t need Workers-specific features.</p>
            <pre><code>import { httpServerHandler } from 'cloudflare:node';
import { createServer } from 'node:http';

// Create your Node.js HTTP server
const server = createServer((req, res) =&gt; {
  if (req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('&lt;h1&gt;Welcome to my Node.js app on Workers!&lt;/h1&gt;');
  } else if (req.url === '/api/status') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok', timestamp: Date.now() }));
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not Found');
  }
});

server.listen(8080);

// Export the server as a Workers handler
export default httpServerHandler({ port: 8080 });
// Or you can simply pass the http.Server instance directly:
// export default httpServerHandler(server);</code></pre>
            
    <div>
      <h2><a href="https://expressjs.com/"><u>Express.js</u></a>, <a href="https://koajs.com/"><u>Koa.js</u></a> and Framework Compatibility</h2>
      <a href="#and-framework-compatibility">
        
      </a>
    </div>
    <p>These HTTP APIs open the door to running popular Node.js frameworks like Express.js on Workers. If any of the middlewares for these frameworks don’t work as expected, please <a href="https://github.com/cloudflare/workerd/issues"><u>open an issue</u></a> to Cloudflare Workers repository.</p>
            <pre><code>import { httpServerHandler } from 'cloudflare:node';
import express from 'express';

const app = express();

app.get('/', (req, res) =&gt; {
  res.json({ message: 'Express.js running on Cloudflare Workers!' });
});

app.get('/api/users/:id', (req, res) =&gt; {
  res.json({
    id: req.params.id,
    name: 'User ' + req.params.id
  });
});

app.listen(3000);
export default httpServerHandler({ port: 3000 });
// Or you can simply pass the http.Server instance directly:
// export default httpServerHandler(app.listen(3000));</code></pre>
            <p>In addition to <a href="https://expressjs.com"><u>Express.js</u></a>, <a href="https://koajs.com/"><u>Koa.js</u></a> is also supported:</p>
            <pre><code>import Koa from 'koa';
import { httpServerHandler } from 'cloudflare:node';

const app = new Koa()

app.use(async ctx =&gt; {
  ctx.body = 'Hello World';
});

app.listen(8080);

export default httpServerHandler({ port: 8080 });</code></pre>
            
    <div>
      <h2>Getting started with serverless <a href="http://node.js"><u>Node.js</u></a> applications</h2>
      <a href="#getting-started-with-serverless-applications">
        
      </a>
    </div>
    <p>The <code>node:http </code>and <code>node:https</code> APIs are available in Workers with Node.js compatibility enabled using the <a href="https://developers.cloudflare.com/workers/configuration/compatibility-dates/#nodejs-compatibility-flag"><code><u>nodejs_compat</u></code></a> compatibility flag with a compatibility date later than 08-15-2025.</p><p>The addition of <code>node:http</code> support brings us closer to our goal of making Cloudflare Workers the best platform for running JavaScript at the edge, whether you're building new applications or migrating existing ones.</p><a href="https://deploy.workers.cloudflare.com/?url=&lt;https://github.com/cloudflare/templates/tree/main/nodejs-http-server-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Ready to try it out? <a href="https://developers.cloudflare.com/workers/runtime-apis/nodejs/"><u>Enable Node.js compatibility</u></a> in your Worker and start exploring the possibilities of familiar<a href="https://developers.cloudflare.com/workers/runtime-apis/nodejs/http/"><u> HTTP APIs at the edge</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Node.js]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Servers]]></category>
            <guid isPermaLink="false">k5sD9WGL8BsJPuqsJj6Fn</guid>
            <dc:creator>Yagiz Nizipli</dc:creator>
            <dc:creator>James M Snell</dc:creator>
        </item>
        <item>
            <title><![CDATA[Build global MySQL apps using Cloudflare Workers and Hyperdrive]]></title>
            <link>https://blog.cloudflare.com/building-global-mysql-apps-with-cloudflare-workers-and-hyperdrive/</link>
            <pubDate>Tue, 08 Apr 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ MySQL comes to Cloudflare Workers and Hyperdrive: MySQL drivers and ORMs are now compatible with Workers runtime, and Hyperdrive allow you to connect to your regional database from Workers. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today, we’re announcing support for MySQL in Cloudflare Workers and Hyperdrive. You can now build applications on Workers that connect to your MySQL databases directly, no matter where they’re hosted, with native MySQL drivers, and with optimal performance. </p><p>Connecting to MySQL databases from Workers has been an area we’ve been focusing on <a href="https://blog.cloudflare.com/relational-database-connectors/"><u>for quite some time</u></a>. We want you to build your apps on Workers with your existing data, even if that data exists in a SQL database in us-east-1. But connecting to traditional SQL databases from Workers has been challenging: it requires making stateful connections to regional databases with drivers that haven’t been designed for <a href="https://blog.cloudflare.com/workerd-open-source-workers-runtime/"><u>the Workers runtime</u></a>. </p><p>After multiple attempts at solving this problem for Postgres, <a href="https://developers.cloudflare.com/hyperdrive/"><u>Hyperdrive</u></a> emerged as our solution that provides the best of both worlds: it supports existing database drivers and libraries while also providing best-in-class performance. And it’s such a critical part of connecting to databases from Workers that we’re making it free (check out the <a href="https://blog.cloudflare.com/how-hyperdrive-speeds-up-database-access"><u>Hyperdrive free tier announcement</u></a>).</p><p>With <a href="http://blog.cloudflare.com/full-stack-development-on-cloudflare-workers"><u>new Node.js compatibility improvements</u></a> and <a href="http://developers.cloudflare.com/changelog/2025-04-08-hyperdrive-mysql-support/"><u>Hyperdrive support for the MySQL wire protocol</u></a>, we’re happy to say MySQL support for Cloudflare Workers has been achieved. If you want to jump into the code and have a MySQL database on hand, this “Deploy to Cloudflare” button will get you setup with a deployed project and will create a repository so you can dig into the code. </p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/mysql-hyperdrive-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>Read on to learn more about how we got MySQL to work on Workers, and why Hyperdrive is critical to making connectivity to MySQL databases fast.</p>
    <div>
      <h2>Getting MySQL to work on Workers</h2>
      <a href="#getting-mysql-to-work-on-workers">
        
      </a>
    </div>
    <p>Until recently, connecting to MySQL databases from Workers was not straightforward. While it’s been possible to make TCP connections from Workers <a href="https://blog.cloudflare.com/workers-tcp-socket-api-connect-databases/"><u>for some time</u></a>, MySQL drivers had many dependencies on Node.js that weren’t available on the Workers runtime, and that prevented their use.</p><p>This led to workarounds being developed. PlanetScale provided a <a href="https://planetscale.com/blog/introducing-the-planetscale-serverless-driver-for-javascript"><u>serverless driver for JavaScript</u></a>, which communicates with PlanetScale servers using HTTP instead of TCP to relay database messages. In a separate effort, a <a href="https://github.com/nora-soderlund/cloudflare-mysql"><u>fork</u></a> of the <a href="https://www.npmjs.com/package/mysql"><u>mysql</u></a> package was created to polyfill the missing Node.js dependencies and modify the <code>mysql</code> package to work on Workers. </p><p>These solutions weren’t perfect. They required using new libraries that either did not provide the level of support expected for production applications, or provided solutions that were limited to certain MySQL hosting providers. They also did not integrate with existing codebases and tooling that depended on the popular MySQL drivers (<a href="https://www.npmjs.com/package/mysql"><u>mysql</u></a> and <a href="https://www.npmjs.com/package/mysql2"><u>mysql2</u></a>). In our effort to enable all JavaScript developers to build on Workers, we knew that we had to support these drivers.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3s4E4XVAbvqRwyk6aITm1h/cb9700eae49d2593c9a834fc7a09018e/1.png" />
          </figure><p><sup><i>Package downloads from </i></sup><a href="https://www.npmjs.com/"><sup><i><u>npm</u></i></sup></a><sup><i> for </i></sup><a href="https://www.npmjs.com/package/mysql"><sup><i><u>mysql</u></i></sup></a><sup><i> and </i></sup><a href="https://www.npmjs.com/package/mysql2"><sup><i><u>mysql2</u></i></sup></a></p><p>Improving our Node.js compatibility story was critical to get these MySQL drivers working on our platform. We first identified <a href="https://nodejs.org/api/net.html"><u>net</u></a> and <a href="https://nodejs.org/api/stream.html"><u>stream</u></a> as APIs that were needed by both drivers. This, complemented by Workers’ <a href="https://blog.cloudflare.com/more-npm-packages-on-cloudflare-workers-combining-polyfills-and-native-code/"><u>nodejs_compat</u></a> to resolve unused Node.js dependencies with <a href="https://github.com/unjs/unenv"><code><u>unenv</u></code></a>, enabled the <a href="https://www.npmjs.com/package/mysql"><u>mysql</u></a> package to work on Workers:</p>
            <pre><code>import { createConnection } from 'mysql';

export default {
 async fetch(request, env, ctx): Promise&lt;Response&gt; {
    const result = await new Promise&lt;any&gt;((resolve) =&gt; {

       const connection = createConnection({
         host: env.DB_HOST,
         user: env.DB_USER,
         password: env.DB_PASSWORD,
         database: env.DB_NAME,
	  port: env.DB_PORT
       });

       connection.connect((error: { message : string }) =&gt; {
          if(error) {
            throw new Error(error.message);
          }
          
          connection.query("SHOW tables;", [], (error, rows, fields) =&gt; {
          connection.end();
         
          resolve({ fields, rows });
        });
       });

      });

     return new Response(JSON.stringify(result), {
       headers: {
         'Content-Type': 'application/json',
       },
     });
 },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>Further work was required to get <a href="https://www.npmjs.com/package/mysql2"><u>mysql2</u></a> working: dependencies on Node.js <a href="https://nodejs.org/api/timers.html"><u>timers</u></a> and the JavaScript <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"><u>eval</u></a> API remained. While we were able to land support for <a href="https://github.com/cloudflare/workerd/pull/3346"><u>timers</u></a> in the Workers runtime, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"><u>eval</u></a> was not an API that we could securely enable in the Workers runtime at this time. </p><p><a href="https://www.npmjs.com/package/mysql2"><u>mysql2</u></a> uses <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"><u>eval</u></a> to optimize the parsing of MySQL results containing large rows with more than 100 columns (see <a href="https://github.com/sidorares/node-mysql2/issues/2055#issuecomment-1614222188"><u>benchmarks</u></a>). This blocked the driver from working on Workers, since the Workers runtime does not support this module. Luckily, <a href="https://github.com/sidorares/node-mysql2/pull/2289"><u>prior effort existed</u></a> to get mysql2 working on Workers using static parsers for handling text and binary MySQL data types without using <code>eval()</code>, which provides similar performance for a majority of scenarios. </p><p>In <a href="https://www.npmjs.com/package/mysql2"><u>mysql2</u></a> version <code>3.13.0</code>, a new option to disable the use of <code>eval()</code> was released to make it possible to use the driver in Cloudflare Workers:</p>
            <pre><code>import { createConnection  } from 'mysql2/promise';

export default {
 async fetch(request, env, ctx): Promise&lt;Response&gt; {
    const connection = await createConnection({
     host: env.DB_HOST,
     user: env.DB_USER,
     password: env.DB_PASSWORD,
     database: env.DB_NAME,
     port: env.DB_PORT

     // The following line is needed for mysql2 to work on Workers (as explained above)
     // mysql2 uses eval() to optimize result parsing for rows with &gt; 100 columns
     // eval() is not available in Workers due to runtime limitations
     // Configure mysql2 to use static parsing with disableEval
     disableEval: true
   });

   const [results, fields] = await connection.query(
     'SHOW tables;'
   );

   return new Response(JSON.stringify({ results, fields }), {
     headers: {
       'Content-Type': 'application/json',
       'Access-Control-Allow-Origin': '*',
     },
   });
 },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>So, with these efforts, it is now possible to connect to MySQL from Workers. But, getting the MySQL drivers working on Workers was only half of the battle. To make MySQL on Workers performant for production uses, we needed to make it possible to connect to MySQL databases with Hyperdrive.</p>
    <div>
      <h2>Supporting MySQL in Hyperdrive</h2>
      <a href="#supporting-mysql-in-hyperdrive">
        
      </a>
    </div>
    <p>If you’re a MySQL developer, <a href="https://developers.cloudflare.com/hyperdrive/"><u>Hyperdrive</u></a> may be new to you. Hyperdrive solves a core problem: connecting from Workers to regional SQL databases is slow. Database drivers <a href="https://blog.cloudflare.com/how-hyperdrive-speeds-up-database-access/"><u>require many roundtrips</u></a> to establish a connection to a database. Without the ability to reuse these connections between Worker invocations, a lot of unnecessary latency is added to your application. </p><p>Hyperdrive solves this problem by pooling connections to your database globally and eliminating unnecessary roundtrips for connection setup. As a plus, Hyperdrive also provides integrated caching to offload popular queries from your database. We wrote an entire deep dive on how Hyperdrive does this, which you should definitely <a href="https://blog.cloudflare.com/how-hyperdrive-speeds-up-database-access/"><u>check out</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/R8bfw57o8KEXHD7EstTmP/eee5182beb931373c25a1c42f5dd0ce3/2.png" />
          </figure><p>Getting Hyperdrive to support MySQL was critical for us to be able to say “Connect from Workers to MySQL databases”. That’s easier said than done. To support a new database type, Hyperdrive needs to be able to parse the wire protocol of the database in question, in this case, the <a href="https://dev.mysql.com/doc/dev/mysql-server/8.4.3/PAGE_PROTOCOL.html"><u>MySQL protocol</u></a>. Once this is accomplished, Hyperdrive can extract queries from protocol messages, cache results across Cloudflare locations, relay messages to a datacenter close to your database, and pool connections reliably close to your origin database. </p><p>Adapting Hyperdrive to parse a new language, MySQL protocol, is a challenge in its own right. But it also presented some notable differences with Postgres. While the intricacies are beyond the scope of this post, the differences in MySQL’s <a href="https://dev.mysql.com/doc/refman/8.4/en/authentication-plugins.html"><u>authentication plugins</u></a> across providers and how MySQL’s connection handshake uses <a href="https://dev.mysql.com/doc/dev/mysql-server/latest/group__group__cs__capabilities__flags.html"><u>capability flags</u></a> required some adaptation of Hyperdrive. In the end, we leveraged the experience we gained in building Hyperdrive for Postgres to iterate on our support for MySQL. And we’re happy to announce MySQL support is available for Hyperdrive, with all of the <a href="https://developers.cloudflare.com/changelog/2025-03-04-hyperdrive-pooling-near-database-and-ip-range-egress/"><u>performance</u></a> <a href="https://developers.cloudflare.com/changelog/2024-12-11-hyperdrive-caching-at-edge/"><u>improvements</u></a> we’ve made to Hyperdrive available from the get-go!</p><p>Now, you can create new Hyperdrive configurations for MySQL databases hosted anywhere (we’ve tested MySQL and MariaDB databases from AWS (including AWS Aurora), GCP, Azure, PlanetScale, and self-hosted databases). You can create Hyperdrive configurations for your MySQL databases from the dashboard or the <a href="https://developers.cloudflare.com/workers/wrangler/"><u>Wrangler CLI</u></a>:</p>
            <pre><code>wrangler hyperdrive create mysql-hyperdrive 
--connection-string="mysql://user:password@db-host.example.com:3306/defaultdb"</code></pre>
            <p>In your Wrangler configuration file, you’ll need to set your Hyperdrive binding to the ID of the newly created Hyperdrive configuration as well as set Node.js compatibility flags:</p>
            <pre><code>{
 "$schema": "node_modules/wrangler/config-schema.json",
 "name": "workers-mysql-template",
 "main": "src/index.ts",
 "compatibility_date": "2025-03-10",
 "observability": {
   "enabled": true
 },
 "compatibility_flags": [
   "nodejs_compat"
 ],
 "hyperdrive": [
   {
     "binding": "HYPERDRIVE",
     "id": "&lt;HYPERDRIVE_CONFIG_ID&gt;"
   }
 ]
}</code></pre>
            <p>From your Cloudflare Worker, the Hyperdrive binding provides you with custom connection credentials that connect to your Hyperdrive configuration. From there onward, all of your queries and database messages will be routed to your origin database by Hyperdrive, leveraging Cloudflare’s network to speed up routing.</p>
            <pre><code>import { createConnection  } from 'mysql2/promise';

export interface Env {
 HYPERDRIVE: Hyperdrive;
}

export default {
 async fetch(request, env, ctx): Promise&lt;Response&gt; {
  
   // Hyperdrive provides new connection credentials to use with your existing drivers
   const connection = await createConnection({
     host: env.HYPERDRIVE.host,
     user: env.HYPERDRIVE.user,
     password: env.HYPERDRIVE.password,
     database: env.HYPERDRIVE.database,
     port: env.HYPERDRIVE.port,

     // Configure mysql2 to use static parsing (as explained above in Part 1)
     disableEval: true 
   });

   const [results, fields] = await connection.query(
     'SHOW tables;'
   );

   return new Response(JSON.stringify({ results, fields }), {
     headers: {
       'Content-Type': 'application/json',
       'Access-Control-Allow-Origin': '*',
     },
   });
 },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>As you can see from this code snippet, you only need to swap the credentials in your JavaScript code for those provided by Hyperdrive to migrate your existing code to Workers. No need to change the ORMs or drivers you’re using! </p>
    <div>
      <h2>Get started building with MySQL and Hyperdrive</h2>
      <a href="#get-started-building-with-mysql-and-hyperdrive">
        
      </a>
    </div>
    <p>MySQL support for Workers and Hyperdrive has been long overdue and we’re excited to see what you build. We published a template for you to get started building your MySQL applications on Workers with Hyperdrive:</p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/mysql-hyperdrive-template"><img src="https://deploy.workers.cloudflare.com/button" /></a>
<p></p><p>As for what’s next, we’re going to continue iterating on our support for MySQL during the beta to support more of the MySQL protocol and MySQL-compatible databases. We’re also going to continue to expand the feature set of Hyperdrive to make it more flexible for your full-stack workloads and more performant for building full-stack global apps on Workers.</p><p>Finally, whether you’re using MySQL, PostgreSQL, or any of the other compatible databases, we think you should be using Hyperdrive to get the best performance. And because we want to enable you to build on Workers regardless of your preferred database, <a href="https://blog.cloudflare.com/how-hyperdrive-speeds-up-database-access"><u>we’re making Hyperdrive available to the Workers free plan. </u></a></p><p>We want to hear your feedback on MySQL, Hyperdrive, and building global applications with Workers. Join the #hyperdrive channel in our <a href="http://discord.cloudflare.com/"><u>Developer Discord</u></a> to ask questions, share what you’re building, and talk to our Product &amp; Engineering teams directly.</p><p>Thank you to <a href="https://github.com/wellwelwel"><u>Weslley Araújo</u></a>, <a href="https://github.com/sidorares"><u>Andrey Sidorov</u></a>, <a href="https://github.com/shiyuhang0"><u>Shi Yuhang</u></a>, <a href="https://github.com/Mini256"><u>Zhiyuan Liang</u></a>, <a href="https://github.com/nora-soderlund"><u>Nora Söderlund</u></a> and other open-source contributors who helped push this initiative forward.</p> ]]></content:encoded>
            <category><![CDATA[Developer Week]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[MySQL]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Hyperdrive]]></category>
            <guid isPermaLink="false">77Nbj8Tnnrr6vMWsDSFekZ</guid>
            <dc:creator>Thomas Gauvin</dc:creator>
            <dc:creator>Andrew Repp</dc:creator>
            <dc:creator>Kirk Nickish</dc:creator>
            <dc:creator>Yagiz Nizipli</dc:creator>
        </item>
        <item>
            <title><![CDATA[New URLPattern API brings improved pattern matching to Node.js and Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/improving-web-standards-urlpattern/</link>
            <pubDate>Mon, 24 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Today we're announcing our latest contribution to Node.js, now available in v23.8.0: URLPattern.  ]]></description>
            <content:encoded><![CDATA[ <p>Today, we are excited to announce that we have contributed an implementation of the <a href="https://urlpattern.spec.whatwg.org"><u>URLPattern</u></a> API to Node.js, and it is available starting with <a href="https://nodejs.org/en/blog/release/v23.8.0"><u>the v23.8.0 update</u></a>. We've done this by adding our URLPattern implementation to <a href="https://github.com/ada-url/ada"><u>Ada URL</u></a>, the high-performance URL parser that now powers URL handling in both Node.js and Cloudflare Workers. This marks an important step toward bringing this API to the broader JavaScript ecosystem.</p><p>Cloudflare Workers has, from the beginning, embraced a standards-based JavaScript programming model, and Cloudflare was one of the founding companies for what has evolved into <a href="https://ecma-international.org/technical-committees/tc55/"><u>ECMA's 55th Technical Committee</u></a>, focusing on interoperability between Web-interoperable runtimes like Workers, Node.js, Deno, and others. This contribution highlights and marks our commitment to this ongoing philosophy. Ensuring that all the JavaScript runtimes work consistently and offer at least a minimally consistent set of features is critical to ensuring the ongoing health of the ecosystem as a whole.</p><p>URLPattern API contribution is just one example of Cloudflare’s ongoing commitment to the open-source ecosystem. We actively contribute to numerous open-source projects including Node.js, V8, and Ada URL, while also maintaining our own open-source initiatives like <a href="https://github.com/cloudflare/workerd"><u>workerd</u></a> and <a href="https://github.com/cloudflare/workers-sdk"><u>wrangler</u></a>. By upstreaming improvements to foundational technologies that power the web, we strengthen the entire developer ecosystem while ensuring consistent features across JavaScript runtimes. This collaborative approach reflects our belief that open standards and shared implementations benefit everyone - reducing fragmentation, improving developer experience and creating a better Internet. </p>
    <div>
      <h2>What is URLPattern?</h2>
      <a href="#what-is-urlpattern">
        
      </a>
    </div>
    <p>URLPattern is a standard published by the <a href="https://whatwg.org/"><u>WHATWG (Web Hypertext Application Technology Working Group)</u></a> which provides a pattern-matching system for URLs. This specification is available at <a href="http://urlpattern.spec.whatwg.org"><u>urlpattern.spec.whatwg.org</u></a>. The API provides developers with an easy-to-use, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions"><u>regular expression (regex)</u></a>-based approach to handling route matching, with built-in support for named parameters, wildcards, and more complex pattern matching that works uniformly across all URL components.</p><p>URLPattern is part of the <a href="https://min-common-api.proposal.wintertc.org/"><u>WinterTC Minimum Common API</u></a>, a soon-to-be standardized subset of web platform APIs designed to ensure interoperability across JavaScript runtimes, particularly for server-side and non-browser environments, and includes other APIs such as <a href="https://url.spec.whatwg.org/#url"><u>URL</u></a> and <a href="https://url.spec.whatwg.org/#urlsearchparams"><u>URLSearchParams</u></a>.</p><p>Cloudflare Workers has supported URLPattern for a number of years now, reflecting our commitment to enabling developers to use standard APIs across both browsers and server-side JavaScript runtimes. Contributing to Node.js and unifying the URLPattern implementation simplifies the ecosystem by reducing fragmentation, while at the same time improving our own implementation in Cloudflare Workers by making it faster and more specification compliant.</p><p>The following example demonstrates how URLPattern is used by creating a pattern that matches URLs with a “/blog/:year/:month/:slug” path structure, then tests if one specific URL string matches this pattern, and extracts the named parameters from a second URL using the exec method.</p>
            <pre><code>const pattern = new URLPattern({
  pathname: '/blog/:year/:month/:slug'
});

if (pattern.test('https://example.com/blog/2025/03/urlpattern-launch')) {
  console.log('Match found!');
}

const result = pattern.exec('https://example.com/blog/2025/03/urlpattern-launch');
console.log(result.pathname.groups.year); // "2025"
console.log(result.pathname.groups.month); // "03"
console.log(result.pathname.groups.slug); // "urlpattern-launch"</code></pre>
            <p>The URLPattern constructor accepts pattern strings or objects defining patterns for individual URL components. The <code>test()</code> method returns a boolean indicating if a URL simply matches the pattern. The <code>exec()</code> method provides detailed match results including captured groups. Behind this simple API, there’s sophisticated machinery working behind the scenes:</p><ol><li><p>When a URLPattern is used, it internally breaks down a URL, matching it against eight distinct components: protocol, username, password, hostname, port, pathname, search, and hash. This component-based approach gives the developer control over which parts of a URL to match.</p></li><li><p>Upon creation of the instance, URLPattern parses your input patterns for each component and compiles them internally into eight specialized regular expressions (one for each component type). This compilation step happens just once when you create an URLPattern object, optimizing subsequent matching operations.</p></li><li><p>During a match operation (whether using <code>test()</code> or <code>exec()</code>), these regular expressions are used to determine if the input matches the given properties. The <code>test()</code> method tells you if there’s a match, while <code>exec()</code> provides detailed information about what was matched, including any named capture groups from your pattern.</p></li></ol>
    <div>
      <h2>Fixing things along the way</h2>
      <a href="#fixing-things-along-the-way">
        
      </a>
    </div>
    <p>While implementing URLPattern, we discovered some inconsistencies between the specification and the <a href="https://github.com/web-platform-tests/wpt/pull/49782"><u>web-platform tests</u></a>, a cross-browser test suite maintained by all major browsers to test conformance to web standard specifications. For instance, we found that <a href="https://github.com/whatwg/urlpattern/issues/240"><u>URLs with non-special protocols (opaque-paths)</u></a> and URLs with invalid characters in hostnames were not correctly defined and processed within the URLPattern specification. We worked actively with the Chromium and the Safari teams to address these issues.</p><p>URLPatterns constructed from hostname components that contain newline or tab characters were expected to fail in the corresponding web-platform tests. This was due to an inconsistency with the original URLPattern implementation and the URLPattern specification.</p>
            <pre><code>const pattern = new URL({ "hostname": "bad\nhostname" });
const matched = pattern.test({ "hostname": "badhostname" });
// This now returns true.</code></pre>
            <p>We opened <a href="https://github.com/whatwg/urlpattern/issues/239"><u>several issues</u></a> to document these inconsistencies and followed up with <a href="https://github.com/whatwg/urlpattern/pull/243"><u>a pull-request to fix the specification</u></a>, ensuring that all implementations will eventually converge on the same corrected behavior. This also resulted in fixing several inconsistencies in web-platform tests, particularly around handling certain types of white space (such as newline or tab characters) in hostnames. </p>
    <div>
      <h2>Getting started with URLPattern</h2>
      <a href="#getting-started-with-urlpattern">
        
      </a>
    </div>
    <p>If you’re interested in using URLPattern today, you can:</p><ul><li><p>Use it natively in modern browsers by accessing the global URLPattern class</p></li><li><p>Try it in Cloudflare Workers (which has had URLPattern support for some time, now with improved spec compliance and performance)</p></li><li><p>Try it in Node.js, <a href="https://nodejs.org/en/blog/release/v23.8.0"><u>starting from v23.8.0</u></a></p></li><li><p>Try it in NativeScript on iOS and Android, <a href="https://blog.nativescript.org/nativescript-8-9-announcement/"><u>starting from v8.9.0</u></a></p></li><li><p>Try it in <a href="https://docs.deno.com/api/web/~/URLPattern"><u>Deno</u></a></p></li></ul><p>Here is a more complex example showing how URLPattern can be used for routing in a Cloudflare Worker — a common use case when building API endpoints or web applications that need to handle different URL paths efficiently and differently. The following example shows a pattern for <a href="https://en.wikipedia.org/wiki/REST"><u>REST APIs</u></a> that matches both “/users” and “/users/:userId”</p>
            <pre><code>const routes = [
  new URLPattern({ pathname: '/users{/:userId}?' }),
];

export default {
  async fetch(request, env, ctx): Promise&lt;Response&gt; {
    const url = new URL(request.url);
    for (const route of routes) {
      const match = route.exec(url);
      if (match) {
        const { userId } = match.pathname.groups;
        if (userId) {
          return new Response(`User ID: ${userId}`);
        }
        return new Response('List of users');
      }
    }
    // No matching route found
    return new Response('Not Found', { status: 404 });
  },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            
    <div>
      <h2>What does the future hold?</h2>
      <a href="#what-does-the-future-hold">
        
      </a>
    </div>
    <p>The contribution of URLPattern to Ada URL and Node.js is just the beginning. We’re excited about the possibilities this opens up for developers across different JavaScript environments.</p><p>In the future, we expect to contribute additional improvements to URLPattern’s performance, enabling more use cases for web application routing. Additionally, efforts to standardize the <a href="https://github.com/whatwg/urlpattern/pull/166"><u>URLPatternList proposal</u></a> will help deliver faster matching capabilities for server-side runtimes. We’re excited about these developments and encourage you to try URLPattern in your projects today.	</p><p>Try it and let us know what you think by creating an issue on the <a href="https://github.com/cloudflare/workerd"><u>workerd repository</u></a>. Your feedback is invaluable as we work to further enhance URLPattern.</p><p>We hope to do our part to build a unified Javascript ecosystem, and encourage others to do the same. This may mean looking for opportunities, such as we have with URLPattern, to share API implementations across backend runtimes. It could mean using or contributing to <a href="https://web-platform-tests.org/"><u>web-platform-tests</u></a> if you are working on a server-side runtime or web-standard APIs, or it might mean joining <a href="https://wintertc.org/faq"><u>WinterTC</u></a> to help define web-interoperable standards for server-side JavaScript.</p> ]]></content:encoded>
            <category><![CDATA[Node.js]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Standards]]></category>
            <guid isPermaLink="false">55t98SAXi3erhs7Wn5dgno</guid>
            <dc:creator>Yagiz Nizipli</dc:creator>
            <dc:creator>James M Snell</dc:creator>
            <dc:creator>Daniel Lemire (Guest author)</dc:creator>
        </item>
    </channel>
</rss>