Hyperdrive Demos and architectures import { GlossaryTooltip, ResourcesBySelector } from "~/components"; Learn how you can use Hyperdrive within your existing application and architecture. Reference architectures Explore the following reference architectures that use Hyperdrive: Getting started import { Render, PackageManagers, Tabs, TabItem } from "~/components"; Hyperdrive accelerates access to your existing databases from Cloudflare Workers, making even single-region databases feel globally distributed. By maintaining a connection pool to your database within Cloudflare's network, Hyperdrive reduces seven round-trips to your database before you can even send a query: the TCP handshake (1x), TLS negotiation (3x), and database authentication (3x). Hyperdrive understands the difference between read and write queries to your database, and caches the most common read queries, improving performance and reducing load on your origin database. This guide will instruct you through: Creating your first Hyperdrive configuration. Creating a Cloudflare Worker and binding it to your Hyperdrive configuration. Establishing a database connection from your Worker to a public database. :::note Hyperdrive currently works with PostgreSQL, MySQL and many compatible databases. This includes CockroachDB and Materialize (which are PostgreSQL-compatible), Supabase, and PlanetScale. Learn more about the databases that Hyperdrive supports. ::: Prerequisites Before you begin, ensure you have completed the following: Sign up for a Cloudflare account if you have not already. Install Node.js. For supported Node.js versions, refer to the Wrangler system requirements. Have a publicly accessible PostgreSQL or MySQL (or compatible) database. If your database is in a private network, refer to Connect to a private database using Workers VPC. 1. Log in Before creating your Hyperdrive binding, log in with your Cloudflare account by running: npx wrangler login You will be directed to a web page asking you to log in to the Cloudflare dashboard. After you have logged in, you will be asked if Wrangler can make changes to your Cloudflare account. Scroll down and select Allow to continue. 2. Create a Worker :::note[New to Workers?] Refer to How Workers works to learn about the Workers serverless execution model works. Go to the Workers Get started guide to set up your first Worker. ::: Create a new project named hyperdrive-tutorial by running: This will create a new hyperdrive-tutorial directory. Your new hyperdrive-tutorial directory will include: A "Hello World" Worker at src/index.ts. A wrangler.jsonc configuration file. wrangler.jsonc is how your hyperdrive-tutorial Worker will connect to Hyperdrive. Enable Node.js compatibility Node.js compatibility is required for database drivers, and needs to be configured for your Workers project. 3. Connect Hyperdrive to a database Hyperdrive works by connecting to your database, pooling database connections globally, and speeding up your database access through Cloudflare's network. It will provide a secure connection string that is only accessible from your Worker which you can use to connect to your database through Hyperdrive. This means that you can use the Hyperdrive connection string with your existing drivers or ORM libraries without needing significant changes to your code. To create your first Hyperdrive database configuration, change into the directory you just created for your Workers project: cd hyperdrive-tutorial To create your first Hyperdrive, you will need: The IP address (or hostname) and port of your database. The database username (for example, hyperdrive-demo). The password associated with that username. The name of the database you want Hyperdrive to connect to. For example, postgres or mysql. Hyperdrive accepts the combination of these parameters in the common connection string format used by database drivers: ```txt postgres://USERNAME:PASSWORD@HOSTNAME_OR_IP_ADDRESS:PORT/database_name ``` Most database providers will provide a connection string you can copy-and-paste directly into Hyperdrive. To create a Hyperdrive connection, run the wrangler command, replacing the placeholder values passed to the --connection-string flag with the values of your existing database: npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" ```txt mysql://USERNAME:PASSWORD@HOSTNAME_OR_IP_ADDRESS:PORT/database_name ``` Most database providers will provide a connection string you can copy-and-paste directly into Hyperdrive. To create a Hyperdrive connection, run the `wrangler` command, replacing the placeholder values passed to the `--connection-string` flag with the values of your existing database: npx wrangler hyperdrive create --connection-string="mysql://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" :::note[Manage caching] By default, Hyperdrive caches eligible read query results. If you wish to disable caching, pass the flag --caching-disabled. Alternatively, you can use the --max-age flag to specify the maximum duration (in seconds) for which items should persist in the cache, before they are evicted. Default value is 60 seconds. Hyperdrive does not invalidate cached read results when your application writes to your database. If your application needs read-after-write consistency, use a separate cache-disabled Hyperdrive configuration for the reads that must return fresh data. Refer to Query caching for guidance and Hyperdrive Wrangler commands for command options. ::: If successful, the command will output your new Hyperdrive configuration: { "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "" } ] } Copy the id field: you will use this in the next step to make Hyperdrive accessible from your Worker script. :::note Hyperdrive will attempt to connect to your database with the provided credentials to verify they are correct before creating a configuration. If you encounter an error when attempting to connect, refer to Hyperdrive's troubleshooting documentation to debug possible causes. ::: 4. Bind your Worker to Hyperdrive 5. Run a query against your database Once you have created a Hyperdrive configuration and bound it to your Worker, you can run a query against your database. Install a database driver To connect to your database, you will need a database driver which allows you to authenticate and query your database. For this tutorial, you will use node-postgres (pg), one of the most widely used PostgreSQL drivers. To install pg, ensure you are in the hyperdrive-tutorial directory. Open your terminal and run the following command: If you are using TypeScript, you should also install the type definitions for pg: With the driver installed, you can now create a Worker script that queries your database. To connect to your database, you will need a database driver which allows you to authenticate and query your database. For this tutorial, you will use mysql2, one of the most widely used MySQL drivers. To install mysql2, ensure you are in the hyperdrive-tutorial directory. Open your terminal and run the following command: With the driver installed, you can now create a Worker script that queries your database. Write a Worker After you have set up your database, you will run a SQL query from within your Worker. Go to your hyperdrive-tutorial Worker and open the index.ts file. The index.ts file is where you configure your Worker's interactions with Hyperdrive. Populate your index.ts file with the following code: // pg 8.16.3 or later is recommended import { Client } from "pg"; export interface Env { // If you set another name in the Wrangler config file as the value for 'binding', // replace "HYPERDRIVE" with the variable name you defined. HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create a new client on each request. Hyperdrive maintains the underlying // database connection pool, so creating a new client is fast. const sql = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); try { // Connect to the database await sql.connect(); // Sample query const results = await sql.query(`SELECT * FROM pg_tables`); // Return result rows as JSON return Response.json(results.rows); } catch (e) { console.error(e); return Response.json( { error: e instanceof Error ? e.message : e }, { status: 500 }, ); } }, } satisfies ExportedHandler; Upon receiving a request, the code above does the following: Creates a new database client configured to connect to your database via Hyperdrive, using the Hyperdrive connection string. Initiates a query via await sql.query() that outputs all tables (user and system created) in the database (as an example query). Returns the response as JSON to the client. Hyperdrive automatically cleans up the client connection when the request ends, and keeps the underlying database connection open in its pool for reuse. After you have set up your database, you will run a SQL query from within your Worker. Go to your hyperdrive-tutorial Worker and open the index.ts file. The index.ts file is where you configure your Worker's interactions with Hyperdrive. Populate your index.ts file with the following code: // mysql2 v3.13.0 or later is required import { createConnection } from "mysql2/promise"; export interface Env { // If you set another name in the Wrangler config file as the value for 'binding', // replace "HYPERDRIVE" with the variable name you defined. HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create a new connection on each request. Hyperdrive maintains the underlying // database connection pool, so creating a new connection is fast. const connection = await createConnection({ host: env.HYPERDRIVE.host, user: env.HYPERDRIVE.user, password: env.HYPERDRIVE.password, database: env.HYPERDRIVE.database, port: env.HYPERDRIVE.port, // The following line is needed for mysql2 compatibility with Workers // mysql2 uses eval() to optimize result parsing for rows with > 100 columns // Configure mysql2 to use static parsing instead of eval() parsing with disableEval disableEval: true, }); try { // Sample query const [results, fields] = await connection.query("SHOW tables;"); // Return result rows as JSON return new Response(JSON.stringify({ results, fields }), { headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }, }); } catch (e) { console.error(e); return Response.json( { error: e instanceof Error ? e.message : e }, { status: 500 }, ); } }, } satisfies ExportedHandler; Upon receiving a request, the code above does the following: Creates a new database client configured to connect to your database via Hyperdrive, using the Hyperdrive connection string. Initiates a query via await connection.query that outputs all tables (user and system created) in the database (as an example query). Returns the response as JSON to the client. Hyperdrive automatically cleans up the client connection when the request ends, and keeps the underlying database connection open in its pool for reuse. Run in development mode (optional) You can test your Worker locally before deploying by running wrangler dev. This runs your Worker code on your machine while connecting to your database. The localConnectionString field works with both local and remote databases and allows you to connect directly to your database from your Worker project running locally. You must specify the SSL/TLS mode if required ( sslmode=require for Postgres, sslMode=REQUIRED for MySQL). To connect to a database during local development, configure localConnectionString in your wrangler.jsonc: { "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "your-hyperdrive-id", "localConnectionString": "postgres://user:password@your-database-host:5432/database", }, ], } Or set an environment variable: export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@your-database-host:5432/database" Then start local development: npx wrangler dev :::note When using wrangler dev with localConnectionString or CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE, Hyperdrive caching does not take effect locally. Alternatively, you can run wrangler dev --remote to test against your deployed Hyperdrive configuration with caching enabled, but this runs your entire Worker in Cloudflare's network instead of locally. Learn more about local development with Hyperdrive. ::: 6. Deploy your Worker You can now deploy your Worker to make your project accessible on the Internet. To deploy your Worker, run: npx wrangler deploy # Outputs: https://hyperdrive-tutorial..workers.dev You can now visit the URL for your newly created project to query your live database. For example, if the URL of your new Worker is hyperdrive-tutorial..workers.dev, accessing https://hyperdrive-tutorial..workers.dev/ will send a request to your Worker that queries your database directly. By finishing this tutorial, you have created a Hyperdrive configuration, a Worker to access that database and deployed your project globally. Next steps Learn more about how Hyperdrive works. How to configure query caching. Troubleshooting common issues when connecting a database to Hyperdrive. If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the Cloudflare Developers community on Discord. Hyperdrive (Postgres & MySQL) import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct, Tabs, TabItem, LinkButton, } from "~/components"; Turn your existing regional database into a globally distributed database. Hyperdrive is a service that accelerates queries you make to existing databases, making it faster to access your data from across the globe from Cloudflare Workers, irrespective of your users' location. Hyperdrive supports any Postgres or MySQL database, including those hosted on AWS, Google Cloud, Azure, Supabase, Neon, and PlanetScale. Hyperdrive also supports Postgres-compatible databases like CockroachDB and Timescale. You do not need to write new code or replace your favorite tools: Hyperdrive works with your existing code and tools you use. Use Hyperdrive's connection details from your Cloudflare Workers application with your existing database drivers and object-relational mapping (ORM) libraries. Examples PostgreSQL ```ts import { Client } from "pg"; export default { async fetch(request, env, ctx): Promise { // Create a new client instance for each request. Hyperdrive maintains the // underlying database connection pool, so creating a new client is fast. const client = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); try { // Connect to the database await client.connect(); // Sample SQL query const result = await client.query("SELECT * FROM pg_tables"); return Response.json(result.rows); } catch (e) { return Response.json({ error: e instanceof Error ? e.message : e }, { status: 500 }); } }, } satisfies ExportedHandler<{ HYPERDRIVE: Hyperdrive }>; ```json { "$schema": "node_modules/wrangler/config-schema.json", "name": "WORKER-NAME", "main": "src/index.ts", "upload_source_maps": true, "compatibility_date": "2025-02-04", "compatibility_flags": [ "nodejs_compat" ], "observability": { "enabled": true }, "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "", "localConnectionString": "" } ] } MySQL ```ts import { createConnection } from 'mysql2/promise'; export default { async fetch(request, env, ctx): Promise { // Create a new connection on each request. Hyperdrive maintains the // underlying database connection pool, so creating a new client is fast. const connection = await createConnection({ host: env.HYPERDRIVE.host, user: env.HYPERDRIVE.user, password: env.HYPERDRIVE.password, database: env.HYPERDRIVE.database, port: env.HYPERDRIVE.port, // This is needed to use mysql2 with Workers // This configures mysql2 to use static parsing instead of eval() parsing (not available on Workers) 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<{ HYPERDRIVE: Hyperdrive }>; ```json { "$schema": "node_modules/wrangler/config-schema.json", "name": "WORKER-NAME", "main": "src/index.ts", "upload_source_maps": true, "compatibility_date": "2025-02-04", "compatibility_flags": [ "nodejs_compat" ], "observability": { "enabled": true }, "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "", "localConnectionString": "" } ] } Get started Features Connect Hyperdrive to your existing database and deploy a Worker that queries it. Hyperdrive allows you to connect to any PostgreSQL or PostgreSQL-compatible database. Hyperdrive allows you to connect to any MySQL database. Default-on caching for your most popular queries executed against your database. Related products Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale. Deploy dynamic front-end applications in record time. More resources ", "timestamp": "", "signature": "" } pscale database create accepts this payload through its --cloudflare-billing flag. Passing @- makes the PlanetScale CLI read it from standard input, which we recommend over passing the signature as a command line argument: npx wrangler hyperdrive planetscale signature | \ pscale database create \ --org \ --engine postgresql \ --cloudflare-billing @- \ --format json pscale database create defaults to Vitess, so pass --engine postgresql for a Postgres database, and --format json is recommended when the output is consumed by an agent. Your PlanetScale credentials stay between you and pscale. Wrangler authorizes the Cloudflare billing side only. The signature is a cryptographically signed token that authorizes creating a database billed to your Cloudflare account. Treat it as a credential and do not share it. Refer to PlanetScale's documentation for the options pscale database create supports. Workers + PlanetScale With Workers, build your application to deploy anywhere across Cloudflare’s global network spanning 330+ cities. You can deploy with a single step, and users in new locations can reach your application without deploying regional infrastructure. Workers compute runs close to your users for low latency. PlanetScale Postgres provides regional databases for your application's control plane or any centralized data that doesn't fit Cloudflare's edge distribution model. Use it for records such as customers, billing, account settings, or other relational data. Hyperdrive provides the connection glue between Workers and PlanetScale. It pools database connections and uses Cloudflare's Cache for eligible read queries to make your application fast even when your database is centralized. How you benefit? Run near the user. When a user sends a request, Cloudflare routes it to a nearby location. Your Worker runs in that location, so request handling starts close to the user. Check for cached reads locally. On the same Cloudflare server handling the Worker request, Hyperdrive sets up your database connection in single digit milliseconds (p90 4ms) so that your database client/driver can send queries immediately. Hyperdrive's connection setup performs TCP connection startup, TLS encryption, and client authentication all on the same local machine, removing any network roundtrips and latency to your database. Once the database connection is ready if the Worker sends a cacheable read query and the result is cached, Hyperdrive returns it without leaving that location. Forward when needed with caching in-between. If no local cached result exists, or if the query cannot be cached, Hyperdrive sends the query across Cloudflare's network to a location close to your PlanetScale database. Hyperdrive checks another cache in that location before it reaches the database; this cache is populated by multiple requests to your database to improve your cache hit ratios similar to tiered caching . Query PlanetScale only when necessary. If neither cache has the result, Hyperdrive sends the query to PlanetScale using an already available pool of database connections. Writes and other uncacheable queries go to PlanetScale so the database remains the source of truth. Multiple layers of caching reduce overall load on your database. Hyperdrive does not invalidate cached read results when your application writes to PlanetScale. If your application needs read-after-write consistency for authentication, sessions, permissions, or another critical path, use a separate cache-disabled Hyperdrive configuration for those reads. Refer to Query caching for guidance. PlanetScale developer experience Postgres or MySQL Choose PlanetScale Postgres or MySQL, and keep using familiar database drivers, object-relational mapping (ORM) libraries, and SQL tooling. Performance and reliability Run production databases on PlanetScale infrastructure with commitment to performance and reliability that power trusted customer workloads. Modern development workflow Use development branches to test database changes, query insights to understand query performance, and the Model Context Protocol (MCP) server to give agents access to database insights data, all without needing a database administrator (DBA). Cloudflare billing When you create a PlanetScale database from the Cloudflare dashboard, you are billed via your Cloudflare account — you will see a line item on your Cloudflare invoice for your PlanetScale usage. The pricing for PlanetScale is the same when you create and use databases via Cloudflare as it is when you buy directly from PlanetScale. For more pricing details, refer to PlanetScale's pricing. You can introspect per-database billing usage via PlanetScale's dashboard. FAQ Support for your PlanetScale databases created via Cloudflare is provided by PlanetScale at their Standard level support or your procured PlanetScale support plan. For help with your PlanetScale database, refer to PlanetScale Support for more information or contact the PlanetScale support team directly via the PlanetScale support portal. For pay-as-you-go Cloudflare accounts, a PlanetScale database is billed daily from when the database is created until the database is deleted. Your database is billed whether or not you execute queries or store data. { const client = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); await client.connect(); const result = await client.query("SELECT * FROM pg_tables"); // No need to call client.end() — Hyperdrive automatically cleans // up the client connection when the request ends. The underlying // pooled connection to your origin database remains open for reuse. return Response.json(result.rows); }, } satisfies ExportedHandler; :::note[Create database clients inside your handlers] You should always create database clients inside your request handlers ( fetch, queue, and similar), not in the global scope. Workers do not allow I/O across requests, and Hyperdrive's distributed connection pooling already solves for connection startup latency. Using a driver-level pool (such as new Pool() or createPool()) in the global script scope will leave you with stale connections that result in failed queries and hard errors. ::: Do not create database clients or connection pools in the global scope. Instead, create a new client inside each handler invocation — Hyperdrive's connection pool ensures this is fast: ```ts import { Client } from "pg"; // 🔴 Bad: Client created in the global scope persists across requests. // Workers do not allow I/O across request contexts, so this client // becomes stale and subsequent queries will throw hard errors. const globalClient = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); await globalClient.connect(); export default { async fetch(request, env, ctx): Promise { // ✅ Good: Client created inside the handler, scoped to this request. // Hyperdrive pools the underlying connection to your origin database, // so creating a new client per request is fast and reliable. const client = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); await client.connect(); const result = await client.query("SELECT * FROM pg_tables"); return Response.json(result.rows); }, } satisfies ExportedHandler; ## Connection lifecycle considerations ### Durable Objects and persistent connections Unlike regular Workers, [Durable Objects](/durable-objects/) can maintain state across multiple requests. If you keep a database client open in a Durable Object, the connection will remain allocated from Hyperdrive's connection pool. Long-lived Durable Objects can exhaust available connections if many objects keep connections open simultaneously. :::caution Be careful when maintaining persistent database connections in Durable Objects. Each open connection consumes resources from Hyperdrive's connection pool, which could impact other parts of your application. Close connections when not actively in use, use connection timeouts, and limit the number of Durable Objects that maintain database connections. ::: ### Long-running transactions Hyperdrive operates in [transaction pooling mode](/hyperdrive/concepts/how-hyperdrive-works/#pooling-mode), where a connection is held for the duration of a transaction. Long-running transactions that contain multiple queries can exhaust Hyperdrive's available connections more quickly because each transaction holds a connection from the pool until it completes. :::tip Keep transactions as short as possible. Perform only the essential queries within a transaction, and avoid including non-database operations (like external API calls or complex computations) inside transaction blocks. ::: Refer to [Limits](/hyperdrive/platform/limits/) to understand how many connections are available for your Hyperdrive configuration based on your Workers plan. ## Related resources - [How Hyperdrive works](/hyperdrive/concepts/how-hyperdrive-works/) - [Connection pooling](/hyperdrive/concepts/connection-pooling/) - [Limits](/hyperdrive/platform/limits/) - [Durable Objects](/durable-objects/) Connection pooling import { Render } from "~/components"; Hyperdrive maintains a pool of connections to your database. These are optimally placed to minimize the latency for your applications. You can configure the amount of connections your Hyperdrive configuration uses to connect to your origin database. This enables you to right-size your connection pool based on your database capacity and application requirements. For instance, if your Worker makes many queries to your database (which cannot be resolved by Hyperdrive's caching), you may want to allow Hyperdrive to make more connections to your database. Conversely, if your Worker makes few queries that actually need to reach your database or if your database allows a small number of database connections, you can reduce the amount of connections Hyperdrive will make to your database. All configurations have a minimum of 5 connections, and with a maximum depending on your Workers plan. Refer to the limits for details. How Hyperdrive pools database connections Hyperdrive will automatically scale the amount of database connections held open by Hyperdrive depending on your traffic and the amount of load that is put on your database. The max_size parameter acts as a soft limit - Hyperdrive may temporarily create additional connections during network issues or high traffic periods to ensure high availability and resiliency. Restart the connection pool Hyperdrive manages the connection pool for you, including automatic detection and recovery from most database failovers. In rare cases, you may need to restart the pool manually as a break-glass action — for example, after a database failover where Hyperdrive has not yet cycled its connections to the new primary. To restart, select your Hyperdrive configuration in the Cloudflare dashboard, go to the Settings tab, and select Restart under Danger zone. Restarting requires the Hyperdrive Admin role. Restarting drains the existing connection pool and forces Hyperdrive to establish new connections to your origin database. After a restart, the Settings tab shows when the configuration was last manually restarted. :::caution Restarting drops all active connections in the pool and forces them to be re-established. In-flight queries may see brief errors while the pool rebuilds. ::: Pooling mode Best practices You can configure connection counts using the Cloudflare dashboard or the Cloudflare API. Consider the following best practices to determine the right limit for your use-case: Start conservatively: Begin with a lower connection count and increase as needed based on your application's performance. Monitor database metrics: Watch your database's connection usage and performance metrics to optimize the connection count. Consider database limits: Ensure your configured connection count doesn't exceed your database's maximum connection limit. Account for multiple configurations: If you have multiple Hyperdrive configurations connecting to the same database, consider the total connection count across all configurations. Next steps Learn more about How Hyperdrive works. Review Hyperdrive limits for your Workers plan. Learn how to Connect to PostgreSQL from Hyperdrive. How Hyperdrive works import { Render } from "~/components"; Connecting to traditional centralized databases from Cloudflare's global network which consists of over 300 data center locations presents a few challenges as queries can originate from any of these locations. If your database is centrally located, queries can take a long time to get to the database and back. Queries can take even longer in situations where you have to establish new connections from stateless environments like Workers, requiring multiple round trips for each Worker invocation. Traditional databases usually handle a maximum number of connections. With any reasonably large amount of distributed traffic, it becomes easy to exhaust these connections. Hyperdrive solves these challenges by managing the number of global connections to your origin database, selectively parsing and choosing which query response to cache while reducing loading on your database and accelerating your database queries. How Hyperdrive makes databases fast globally Hyperdrive accelerates database queries by: Performing the connection setup for new database connections near your Workers Pooling existing connections near your database Caching query results This ensures you have optimal performance when connecting to your database from Workers (whether your queries are cached or not). 1. Edge connection setup When a database driver connects to a database from a Cloudflare Worker directly, it will first go through the connection setup. This may require multiple round trips to the database in order to verify and establish a secure connection. This can incur additional network latency due to the distance between your Cloudflare Worker and your database. With Hyperdrive, this connection setup occurs between your Cloudflare Worker and Hyperdrive on the edge, as close to your Worker as possible (see diagram, label 1. Connection setup). This incurs significantly less latency, since the connection setup is completed within the same location. Learn more about how connections work between Workers and Hyperdrive in Connection lifecycle. 2. Connection Pooling Hyperdrive creates a pool of connections to your database that can be reused as your application executes queries against your database. The pool of database connections is placed in one or more regions closest to your origin database. This minimizes the latency incurred by roundtrips between your Cloudflare Workers and database to establish new connections. This also ensures that as little network latency is incurred for uncached queries. If the connection pool has pre-existing connections, the connection pool will try and reuse that connection (see diagram, label 2. Existing warm connection). If the connection pool does not have pre-existing connections, it will establish a new connection to your database and use that to route your query. This aims at reusing and creating the least number of connections possible as required to operate your application. :::note Hyperdrive automatically manages the connection pool properties for you, including limiting the total number of connections to your origin database. Refer to Limits to learn more. ::: Learn more about connection pooling behavior and configuration in Connection pooling. 3. Query Caching Hyperdrive supports caching of non-mutating (read) queries to your database. When queries are sent via Hyperdrive, Hyperdrive parses the query and determines whether the query is a mutating (write) or non-mutating (read) query. For non-mutating queries, Hyperdrive caches the response for the configured max_age. When your Worker sends a later query that matches the original, Hyperdrive returns the cached response instead of sending the query back to the origin database. Caching reduces the burden on your origin database and accelerates the response times for your queries. Hyperdrive does not invalidate cached read query results when your application writes to your database. If your application needs read-after-write consistency, refer to Query caching for guidance on using a separate cache-disabled Hyperdrive configuration for reads that must return fresh data. Learn more about query caching behavior and configuration in Query caching. Pooling mode Related resources Connection lifecycle Query caching Connection pooling Concepts Learn about the core concepts and architecture behind Hyperdrive. Query caching import { TabItem, Tabs, WranglerConfig } from "~/components"; Hyperdrive automatically caches cacheable read queries that your Worker sends to your database when query caching is turned on. This reduces database load and avoids a network round trip to your database for popular queries. Query caching is enabled by default. What does Hyperdrive cache? Hyperdrive uses database protocols to differentiate between a mutating query (a query that writes to the database) and a non-mutating query (a read-only query). Hyperdrive caches eligible read-only query responses and does not cache writes. Besides determining the difference between a SELECT and an INSERT, Hyperdrive also parses the database wire-protocol and uses it to differentiate between a mutating or non-mutating query. For example, a read query that populates the front page of a news site would be cached: -- Cacheable: uses a parameterized date value instead of CURRENT_DATE SELECT * FROM articles WHERE DATE(published_time) = $1 ORDER BY published_time DESC LIMIT 50 -- Cacheable: uses a parameterized date value instead of CURDATE() SELECT * FROM articles WHERE DATE(published_time) = ? ORDER BY published_time DESC LIMIT 50 Mutating queries (including INSERT, UPSERT, or CREATE TABLE) and queries that use functions designated as volatile or stable by PostgreSQL are not cached: ```sql -- Not cached: mutating queries INSERT INTO users(id, name, email) VALUES(555, 'Matt', 'hello@example.com'); -- Not cached: LASTVAL() is a volatile function SELECT LASTVAL(), * FROM articles LIMIT 50; -- Not cached: NOW() is a stable function SELECT * FROM events WHERE created_at > NOW() - INTERVAL '1 hour'; ``` ```sql -- Not cached: mutating queries INSERT INTO users(id, name, email) VALUES(555, 'Thomas', 'hello@example.com'); -- Not cached: LAST_INSERT_ID() is a volatile function SELECT LAST_INSERT_ID(), * FROM articles LIMIT 50; -- Not cached: NOW() returns a non-deterministic value SELECT * FROM events WHERE created_at > NOW() - INTERVAL 1 HOUR; ``` Common PostgreSQL functions that are not cacheable include: Function PostgreSQL volatility category Cached NOW() STABLE No CURRENT_TIMESTAMP STABLE No CURRENT_DATE STABLE No CURRENT_TIME STABLE No LOCALTIME STABLE No LOCALTIMESTAMP STABLE No TIMEOFDAY() VOLATILE No RANDOM() VOLATILE No LASTVAL() VOLATILE No TXID_CURRENT() STABLE No Only functions designated as IMMUTABLE by PostgreSQL (functions whose return value never changes for the same inputs) are compatible with Hyperdrive caching. If your query uses a STABLE or VOLATILE function, move the function call to your application code and pass the resulting value as a query parameter instead. :::caution[Do not use SQL comments as cache controls] Hyperdrive uses text-based pattern matching to detect some uncacheable functions in your queries. This can include function names inside SQL comments. Comments that contain volatile or uncacheable function names, such as -- NOW() or -- RANDOM(), can cause the query to be treated as uncacheable. However, comment text that does not contain uncacheable function names does not change the cache key. For example: A: /* some text here */ SELECT * FROM some_table; B: /* some different text here */ SELECT * FROM some_table; Both A and B share the same cached value. If A is run before B, B will receive the value cached by A. Hyperdrive does not document SQL comments as a cache-control API, and parser behavior can differ between database engines. Use a cache-disabled Hyperdrive configuration when you need a guaranteed fresh read. Avoid referencing uncacheable function names anywhere in query text, including comments. ::: Default cache settings The default caching behavior for Hyperdrive is: max_age = 60 seconds (1 minute) stale_while_revalidate = 15 seconds The max_age setting determines the maximum lifetime a query response will be served from cache. Cached responses may be evicted from the cache prior to this time if they are rarely used. The stale_while_revalidate setting allows Hyperdrive to continue serving stale cache results for an additional period of time while it is revalidating the cache. In most cases, revalidation should happen rapidly. You can set a maximum max_age of 1 hour. Read-after-write behavior Hyperdrive does not purge or invalidate cached read query results when your application writes to your database. A later matching SELECT can return the cached result until the configured max_age expires. Hyperdrive can also serve the result during the stale_while_revalidate window while it refreshes the cache in the background. Writes still go to your database. Hyperdrive only caches eligible read query responses. This means you should choose a caching strategy based on how fresh each read must be: Use query caching for reads that can tolerate brief staleness. Good examples include public content, dashboards, search results, product catalogs, and other high-volume reads where a short delay after writes is acceptable. Lower max_age and stale_while_revalidate when a short stale window works. This keeps query caching enabled while reducing how long Hyperdrive can serve an older result. Use a cache-disabled Hyperdrive configuration for reads that must be fresh. Create a second Hyperdrive configuration with --caching-disabled, bind it alongside your cached configuration, and route those reads through the cache-disabled binding. Good examples include authentication, sessions, permissions, billing state, admin settings, and reads immediately after a write. Refer to Disable caching for an example. Disable query caching everywhere only when most reads must be fresh. You still get Hyperdrive's connection pooling and fast connection setup when caching is disabled. If an object-relational mapping (ORM) library or authentication library owns the SQL, create separate database clients for the cached and cache-disabled Hyperdrive bindings. Pass the cache-disabled client to the library or module that needs fresh reads, and use the cached client for reads that can tolerate the configured stale window. Disable caching Disable caching on a per-Hyperdrive configuration basis by using the Wrangler CLI to set the --caching-disabled option. To create a separate cache-disabled Hyperdrive configuration against the same database: npx wrangler hyperdrive create my-database-fresh --connection-string="" --caching-disabled To turn off caching on an existing Hyperdrive configuration: npx wrangler hyperdrive update --caching-disabled You can configure multiple Hyperdrive connections from a single application: one connection that enables caching for popular queries, and a second connection for fresh reads that should not use query caching. When you use multiple Hyperdrive configurations for the same database, account for the total origin connections across configurations. Refer to Tune connection pool for guidance. For example, using database drivers: ```ts title="index.ts" export default { async fetch(request, env, ctx): Promise { // Create clients inside your handler — not in global scope const client = postgres(env.HYPERDRIVE.connectionString); // Use the cache-disabled binding for auth, permissions, and reads after writes. const clientNoCache = postgres(env.HYPERDRIVE_CACHE_DISABLED.connectionString); // ... }, } satisfies ExportedHandler; ``` ```ts title="index.ts" export default { async fetch(request, env, ctx): Promise { // Create connections inside your handler — not in global scope const connection = await createConnection({ host: env.HYPERDRIVE.host, user: env.HYPERDRIVE.user, password: env.HYPERDRIVE.password, database: env.HYPERDRIVE.database, port: env.HYPERDRIVE.port, }); // Use the cache-disabled binding for auth, permissions, and reads after writes. const connectionNoCache = await createConnection({ host: env.HYPERDRIVE_CACHE_DISABLED.host, user: env.HYPERDRIVE_CACHE_DISABLED.user, password: env.HYPERDRIVE_CACHE_DISABLED.password, database: env.HYPERDRIVE_CACHE_DISABLED.database, port: env.HYPERDRIVE_CACHE_DISABLED.port, }); // ... }, } satisfies ExportedHandler; ``` The Wrangler configuration remains the same both for PostgreSQL and MySQL. { "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "", }, { "binding": "HYPERDRIVE_CACHE_DISABLED", "id": "", }, ], } Next steps For more information, refer to How Hyperdrive works. To connect to PostgreSQL, refer to Connect to PostgreSQL. For troubleshooting guidance, refer to Troubleshoot and debug. Connect to a private database using Workers VPC (Recommended) import { Render, Tabs, TabItem } from "~/components"; Workers VPC provides a way to connect Hyperdrive to a private database without configuring Cloudflare Access applications or service tokens. Instead, you create a TCP VPC Service that points to your database and pass its service ID to Hyperdrive. For the Tunnel and Access approach, refer to Connect to a private database using Tunnel. How it works When your database is isolated within a private network (such as a virtual private cloud or an on-premise network), you must enable a secure connection from your network to Cloudflare. Cloudflare Tunnel is used to establish a secure outbound connection from your private network to Cloudflare. A VPC Service is used to route traffic from your Worker through the tunnel to your database, without requiring Cloudflare Access applications or service tokens. A request from the Cloudflare Worker to the origin database goes through Hyperdrive, the VPC Service, and the Cloudflare Tunnel established by cloudflared. cloudflared must be running in the private network in which your database is accessible. flowchart LR A[Cloudflare Worker] --> B[Hyperdrive] --> C[VPC Service] --> D[Cloudflare Tunnel] --> E[Private Database] Prerequisites A database in your private network, configured to use TLS/SSL. A Cloudflare Tunnel running in a network that can reach your database. The Connectivity Directory Admin role on your Cloudflare account to create VPC Services. 1. Set up a Cloudflare Tunnel If you do not already have a tunnel running in the same network as your database, create one. The tunnel must be able to reach your database host and port from within the private network. For full tunnel documentation, refer to Cloudflare Tunnel for Workers VPC. 2. Create a TCP VPC Service Create a VPC Service of type tcp that points to your database. Set the --app-protocol flag to postgresql or mysql so that Hyperdrive can optimize connections. npx wrangler vpc service create my-postgres-db \ --type tcp \ --tcp-port 5432 \ --app-protocol postgresql \ --tunnel-id \ --ipv4 npx wrangler vpc service create my-mysql-db \ --type tcp \ --tcp-port 3306 \ --app-protocol mysql \ --tunnel-id \ --ipv4 Replace: with the tunnel ID from step 1. with the private IP address of your database (for example, 10.0.0.5). You can also use --hostname with a DNS name instead of --ipv4. The command will return a service ID. Save this value for the next step. You can also create a TCP VPC Service from the Workers VPC dashboard. Refer to VPC Services for all configuration options. TLS certificate verification Unlike Hyperdrive, which does not verify the origin server certificate by default, Workers VPC defaults to verify_full — it verifies both the certificate chain and the hostname. If your database uses a self-signed certificate or a certificate from a private certificate authority (CA), the TLS handshake will fail unless you adjust the verification mode. For databases with self-signed certificates, add --cert-verification-mode when creating the VPC Service: verify_ca — Verifies the certificate chain but skips hostname verification. Use this when your database has a certificate signed by a CA you control but the hostname does not match the certificate. disabled — Skips certificate verification entirely. Use this only for development or testing. For example, to create a VPC Service for a PostgreSQL database with a self-signed certificate: npx wrangler vpc service create my-postgres-db \ --type tcp \ --tcp-port 5432 \ --app-protocol postgresql \ --tunnel-id \ --ipv4 \ --cert-verification-mode verify_ca To update an existing VPC Service, use wrangler vpc service update with the same flag. :::note Workers VPC trusts publicly trusted certificates and Cloudflare Origin CA certificates. Uploading a custom CA certificate to Workers VPC is not supported yet. If your database uses a certificate signed by a private CA, set --cert-verification-mode to verify_ca or disabled until custom CA support is available. ::: For the full list of verification modes, refer to TLS certificate verification mode. 3. Create a Hyperdrive configuration Use the --service-id flag to point Hyperdrive at the VPC Service you created. When you use --service-id, you do not provide --origin-host, --origin-port, or --connection-string. Hyperdrive routes traffic through the VPC Service instead. npx wrangler hyperdrive create \ --service-id \ --database \ --user \ --password \ --scheme postgresql npx wrangler hyperdrive create \ --service-id \ --database \ --user \ --password \ --scheme mysql Replace: with the service ID from step 2. with the name of your database. and with your database credentials. If successful, the command will output a Hyperdrive configuration with an id field. Copy this ID for the next step. :::note The --service-id flag conflicts with --origin-host, --origin-port, --connection-string, --access-client-id, and --access-client-secret. You cannot combine these options. To update an existing Hyperdrive configuration to use a VPC Service, run wrangler hyperdrive update with the --service-id flag. ::: 4. Bind Hyperdrive to a Worker 5. Query the database Use node-postgres ( pg) to send a test query. Deploy your Worker: npx wrangler deploy If you receive a list of pg_tables from your database when you access your deployed Worker, Hyperdrive is connected to your private database through Workers VPC. Use mysql2 to send a test query. Deploy your Worker: npx wrangler deploy If you receive a list of tables from your database when you access your deployed Worker, Hyperdrive is connected to your private database through Workers VPC. Next steps Learn more about how Hyperdrive works. Configure query caching for Hyperdrive. Review VPC Service configuration options including TLS certificate verification. Set up high availability tunnels for production workloads. Troubleshoot common issues when connecting a database to Hyperdrive. Connect to a private database using Tunnel import { TabItem, Tabs, Render, Steps, Details } from "~/components"; Hyperdrive can securely connect to your private databases using Cloudflare Tunnel and Cloudflare Access. :::note You can also connect Hyperdrive to a private database using Workers VPC (Recommended), which does not require configuring Access applications or service tokens. ::: How it works When your database is isolated within a private network (such as a virtual private cloud or an on-premise network), you must enable a secure connection from your network to Cloudflare. Cloudflare Tunnel is used to establish the secure tunnel connection. Cloudflare Access is used to restrict access to your tunnel such that only specific Hyperdrive configurations can access it. A request from the Cloudflare Worker to the origin database goes through Hyperdrive, Cloudflare Access, and the Cloudflare Tunnel established by cloudflared. cloudflared must be running in the private network in which your database is accessible. The Cloudflare Tunnel will establish an outbound bidirectional connection from your private network to Cloudflare. Cloudflare Access will secure your Cloudflare Tunnel to be only accessible by your Hyperdrive configuration. :::caution[Warning] If your organization also uses Super Bot Fight Mode, keep Definitely Automated set to Allow. Otherwise, tunnels might fail with a websocket: bad handshake error. ::: Prerequisites A database in your private network, configured to use TLS/SSL. A hostname on your Cloudflare account, which will be used to route requests to your database. 1. Create a tunnel in your private network 1.1. Create a tunnel First, create a Cloudflare Tunnel in your private network to establish a secure connection between your network and Cloudflare. Your network must be configured such that the tunnel has permissions to egress to the Cloudflare network and access the database within your network. 1.2. Connect your database using a public hostname Your tunnel must be configured to use a public hostname on Cloudflare so that Hyperdrive can route requests to it. If you don't have a hostname on Cloudflare yet, you will need to register a new hostname or add a zone to Cloudflare to proceed. In the Published application routes tab, choose a Domain and specify any subdomain or path information. This will be used in your Hyperdrive configuration to route to this tunnel. In the Service section, specify Type TCP and the URL and configured port of your database, such as localhost:5432 or my-database-host.database-provider.com:5432. This address will be used by the tunnel to route requests to your database. Select Save tunnel. :::note If you are setting up the tunnel through the CLI instead (locally-managed tunnel), you will have to complete these steps manually. Follow the Cloudflare Zero Trust documentation to add a public hostname to your tunnel and configure the public hostname to route to the address of your database. ::: 2. Create and configure Hyperdrive to connect to the Cloudflare Tunnel To restrict access to the Cloudflare Tunnel to Hyperdrive, a Cloudflare Access application must be configured with a Policy that requires requests to contain a valid Service Auth token. The Cloudflare dashboard can automatically create and configure the underlying Cloudflare Access application, Service Auth token, and Policy on your behalf. Alternatively, you can manually create the Access application and configure the Policies. 2.1. (Automatic) Create a Hyperdrive configuration in the Cloudflare dashboard Create a Hyperdrive configuration in the Cloudflare dashboard to automatically configure Hyperdrive to connect to your Cloudflare Tunnel. 1. In the [Cloudflare dashboard](https://dash.cloudflare.com/?to=/:account/workers/hyperdrive), navigate to **Storage & Databases > Hyperdrive** and click **Create configuration**. 2. Select **Private database**. 3. In the **Networking details** section, select the tunnel you are connecting to. 4. In the **Networking details** section, select the hostname associated to the tunnel. If there is no hostname for your database, return to step [1.2. Connect your database using a public hostname](/hyperdrive/configuration/connect-to-private-database/#12-connect-your-database-using-a-public-hostname). 5. In the **Access Service Authentication Token** section, select **Create new (automatic)**. 6. In the **Access Application** section, select **Create new (automatic)**. 7. In the **Database connection details** section, enter the database **name**, **user**, and **password**. ### 2.1. (Manual) Create a service token The service token will be used to restrict requests to the tunnel, and is needed for the next step. In the Cloudflare dashboard, go to Zero Trust > Access controls > Service credentials > Service Tokens. Select Create Service Token. Name the service token. The name allows you to easily identify events related to the token in the logs and to revoke the token individually. Set a Service Token Duration of Non-expiring. This prevents the service token from expiring, ensuring it can be used throughout the life of the Hyperdrive configuration. Select Generate token. You will see the generated Client ID and Client Secret for the service token, as well as their respective request headers. Copy the Access Client ID and Access Client Secret. These will be used when creating the Hyperdrive configuration. :::caution This is the only time Cloudflare Access will display the Client Secret. If you lose the Client Secret, you must regenerate the service token. ::: 2.2. (Manual) Create an Access application to secure the tunnel Cloudflare Access will be used to verify that requests to the tunnel originate from Hyperdrive using the service token created above. 1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Applications**. Select Create new application. Select Self-hosted and private. Select Add public hostname and enter the subdomain and domain that was previously set for the tunnel application. Select Create new policy. Enter a Policy name and set the Action to Service Auth. Create an Include rule. Specify a Selector of Service Token and the Value of the service token you created in step 2. Create a service token. Save the policy. In Identity providers, turn off Accept all available identity providers and clear all identity providers. In Session Duration, select No duration, expires immediately. (Optional) Go to Additional settings. Turn off Show application in App Launcher. Select Create. 2.3. (Manual) Create a Hyperdrive configuration To create a Hyperdrive configuration for your private database, you'll need to specify the Access application and Cloudflare Tunnel information upon creation. # wrangler v3.65 and above required npx wrangler hyperdrive create --host= --user= --password= --database= --access-client-id= --access-client-secret= resource "cloudflare_hyperdrive_config" "" { account_id = "" name = "" origin = { host = "" database = "" user = "" password = "" scheme = "postgres" access_client_id = "" access_client_secret = "" } caching = { disabled = false } } This will create a Hyperdrive configuration using the usual database information (database name, database host, database user, and database password). In addition, it will also set the Access Client ID and the Access Client Secret of the Service Token. When Hyperdrive makes requests to the tunnel, requests will be intercepted by Access and validated using the credentials of the Service Token. :::note When creating the Hyperdrive configuration for the private database, you must enter the access-client-id and the access-client-secret, and omit the port. Hyperdrive will route database messages to the public hostname of the tunnel, and the tunnel will rely on its service configuration (as configured in 1.2. Connect your database using a public hostname) to route requests to the database within your private network. ::: 3. Query your Hyperdrive configuration from a Worker (optional) To test your Hyperdrive configuration to the database using Cloudflare Tunnel and Access, use the Hyperdrive configuration ID in your Worker and deploy it. 3.1. Create a Hyperdrive binding 3.2. Query your database Validate that you can connect to your database from Workers and make queries. Use node-postgres ( pg) to send a test query to validate that the connection has been successful. Now, deploy your Worker: npx wrangler deploy If you successfully receive the list of pg_tables from your database when you access your deployed Worker, your Hyperdrive has now been configured to securely connect to a private database using Cloudflare Tunnel and Cloudflare Access. Use mysql2 to send a test query to validate that the connection has been successful. Now, deploy your Worker: npx wrangler deploy If you successfully receive the list of tables from your database when you access your deployed Worker, your Hyperdrive has now been configured to securely connect to a private database using Cloudflare Tunnel and Cloudflare Access. Troubleshooting If you encounter issues when setting up your Hyperdrive configuration with tunnels to a private database, consider these common solutions, in addition to general troubleshooting steps for Hyperdrive: Ensure your database is configured to use TLS (SSL). Hyperdrive requires TLS (SSL) to connect. Firewall and networking configuration import { TabItem, Tabs, Render, WranglerConfig } from "~/components"; Hyperdrive uses the Cloudflare IP address ranges to connect to your database. If you decide to restrict the IP addresses that can access your database with firewall rules, the IP address ranges listed in this reference need to be allow-listed in your database's firewall and networking configurations. You can connect to your database from Hyperdrive using any of the 3 following networking configurations: Configure your database to allow inbound connectivity from the public Internet (all IP address ranges). Configure your database to allow inbound connectivity from the public Internet, with only the IP address ranges used by Hyperdrive allow-listed in an IP access control list (ACL). Configure your database to allow inbound connectivity from a private network, and run a Cloudflare Tunnel instance in your private network to enable Hyperdrive to connect from the Cloudflare network to your private network. Refer to documentation on connecting to a private database using Tunnel. Configuration import { DirectoryListing } from "~/components"; Local development import { WranglerConfig } from "~/components"; Hyperdrive can be used when developing and testing your Workers locally. Wrangler, the command-line interface for Workers, provides two options for local development: wrangler dev (default): Runs your Worker code locally on your machine. You configure a localConnectionString to connect directly to a database (either local or remote). Hyperdrive query caching does not take effect in this mode. wrangler dev --remote: Runs your Worker on Cloudflare's using your deployed Hyperdrive configuration. This is useful for testing with Hyperdrive's connection pooling and query caching enabled. Use wrangler dev By default, wrangler dev runs your Worker code locally on your machine. To connect to a database during local development, configure a localConnectionString that points directly to your database. The localConnectionString works with both local and remote databases: Local databases: Connect to a database instance running on your machine (for example, postgres://user:password@localhost:5432/database) Remote databases: Connect directly to remote databases over TLS (for example, postgres://user:password@remote-host.example.com:5432/database?sslmode=require or mysql://user:password@remote-host.example.com:3306/database?sslMode=required). You must specify the SSL/TLS mode if required. :::note When using localConnectionString, Hyperdrive's connection pooling and query caching do not take effect. Your Worker connects directly to the database without going through Hyperdrive. ::: Configure with environment variable The recommended approach is to use an environment variable to avoid committing credentials to source control: # Your configured Hyperdrive binding is "HYPERDRIVE" export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@your-database-host:5432/database" npx wrangler dev The environment variable format is CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_, where is the name of the binding assigned to your Hyperdrive in your Wrangler configuration file. To unset an environment variable: unset CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_ For example, to set the connection string for a local database: export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@localhost:5432/databasename" npx wrangler dev Configure in Wrangler configuration file Alternatively, you can set localConnectionString in your Wrangler configuration file: { "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "c020574a-5623-407b-be0c-cd192bab9545", "localConnectionString": "postgres://user:password@localhost:5432/databasename" } ] } If both an environment variable and localConnectionString in the Wrangler configuration file are set, the environment variable takes precedence. Use wrangler dev --remote When you run wrangler dev --remote, your Worker runs in Cloudflare's network and uses your deployed Hyperdrive configuration. This means: Your Worker code executes in Cloudflare's production environment, not locally Hyperdrive's connection pooling and query caching are active You connect to the database configured in your Hyperdrive configuration (created with wrangler hyperdrive create) Changes made during the session interact with remote resources This mode is useful for testing how your Worker behaves with Hyperdrive's features enabled before deploying. Configure your Hyperdrive binding in wrangler.jsonc: { "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "your-hyperdrive-id", }, ], } To start a remote development session: npx wrangler dev --remote :::note The localConnectionString field is not used with wrangler dev --remote. Instead, your Worker connects to the database configured in your deployed Hyperdrive configuration. ::: :::caution Use wrangler dev --remote with caution. Since your Worker runs in Cloudflare's production environment, any database writes or side effects will affect your production data. ::: Refer to the wrangler dev documentation to learn more about how to configure a local development session. Related resources Use wrangler dev to run your Worker and Hyperdrive locally and debug issues before deploying. Learn how Hyperdrive works. Understand how to configure query caching in Hyperdrive. Rotating database credentials import { TabItem, Tabs, Render, WranglerConfig } from "~/components"; You can change the connection information and credentials of your Hyperdrive configuration in one of two ways: Create a new Hyperdrive configuration with the new connection information, and update your Worker to use the new Hyperdrive configuration. Update the existing Hyperdrive configuration with the new connection information and credentials. Use a new Hyperdrive configuration Creating a new Hyperdrive configuration to update your database credentials allows you to keep your existing Hyperdrive configuration unchanged, gradually migrate your Worker to the new Hyperdrive configuration, and easily roll back to the previous configuration if needed. To create a Hyperdrive configuration that connects to an existing PostgreSQL or MySQL database, use the Wrangler CLI or the Cloudflare dashboard. # wrangler v3.11 and above required npx wrangler hyperdrive create my-updated-hyperdrive --connection-string="" The command above will output the ID of your Hyperdrive. Set this ID in the Wrangler configuration file for your Workers project: { // required for database drivers to function "compatibility_flags": [ "nodejs_compat" ], "compatibility_date": "$today", "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "" } ] } To update your Worker to use the new Hyperdrive configuration, redeploy your Worker or use gradual deployments. Update the existing Hyperdrive configuration You can update the configuration of an existing Hyperdrive configuration using the wrangler CLI. # wrangler v3.11 and above required npx wrangler hyperdrive update --origin-host --origin-password --origin-user --database --origin-port :::note Updating the settings of an existing Hyperdrive configuration does not purge Hyperdrive's cache and does not tear down the existing database connection pool. New connections will be established using the new connection information. To drain the existing pool and force new connections immediately, restart the connection pool. ::: SSL/TLS certificates import { TabItem, Tabs, Render, WranglerConfig, DashButton, } from "~/components"; Hyperdrive provides additional ways to secure connectivity to your database. Hyperdrive supports: Server certificates for TLS (SSL) modes such as verify-ca/ VERIFY_CA and verify-full/ VERIFY_IDENTITY for increased security. When configured, Hyperdrive will verify that the certificates have been signed by the expected certificate authority (CA) to avoid man-in-the-middle attacks. Client certificates for Hyperdrive to authenticate itself to your database with credentials beyond username/password. To properly use client certificates, your database must be configured to verify the client certificates provided by a client, such as Hyperdrive, to allow access to the database. Hyperdrive can be configured to use only server certificates, only client certificates, or both depending on your security requirements and database configurations. Server certificates (TLS/SSL modes) Hyperdrive supports common encryption TLS/SSL modes to connect to your database. The mode names differ between PostgreSQL and MySQL: PostgreSQL MySQL Description require (default) REQUIRED (default) TLS is required for encrypted connectivity and server certificates are validated (based on WebPKI). verify-ca VERIFY_CA Hyperdrive will verify that the database server is trustworthy by verifying that the certificates of the server have been signed by the expected root certificate authority or intermediate certificate authority. verify-full VERIFY_IDENTITY In addition to verify-ca/ VERIFY_CA checks, Hyperdrive requires the database hostname to match a Subject Alternative Name (SAN) or Common Name (CN) on the certificate. By default, all Hyperdrive configurations are encrypted with SSL/TLS ( require/ REQUIRED). This requires your database to be configured to accept encrypted connections (with SSL/TLS). You can configure Hyperdrive to use verify-ca/ VERIFY_CA and verify-full/ VERIFY_IDENTITY for a more stringent security configuration, which provide additional verification checks of the server's certificates. This helps guard against man-in-the-middle attacks. To configure Hyperdrive to verify the certificates of the server, you must provide Hyperdrive with the certificate of the root certificate authority (CA) or an intermediate certificate which has been used to sign the certificate of your database. Step 1: Upload the root certificate authority (CA) certificate Using Wrangler, you can upload your root certificate authority (CA) certificate: # requires Wrangler 4.9.0 or greater npx wrangler cert upload certificate-authority --ca-cert \.pem --name \ --- Uploading CA Certificate tmp-cert... Success! Uploaded CA Certificate ID: ... :::note You must use the CA certificate bundle that is for your specific region. You cannot use a CA certificate bundle that contains more than one CA certificate, such as a global bundle of CA certificates containing each region's certificate. ::: Step 2: Create your Hyperdrive configuration using the CA certificate and the SSL mode Once your CA certificate has been created, you can create a Hyperdrive configuration with the newly created certificates using either the dashboard or Wrangler. You must also specify the SSL mode to use ( verify-ca/ verify-full for PostgreSQL or VERIFY_CA/ VERIFY_IDENTITY for MySQL). Using Wrangler, enter the following command in your terminal to create a Hyperdrive configuration with the CA certificate and SSL mode: # PostgreSQL with verify-full npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" --ca-certificate-id --sslmode verify-full # MySQL with VERIFY_IDENTITY npx wrangler hyperdrive create --connection-string="mysql://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" --ca-certificate-id --sslmode VERIFY_IDENTITY From the dashboard, follow these steps to create a Hyperdrive configuration with server certificates: In the Cloudflare dashboard, go to the Hyperdrive page. Select Create configuration. Select Server certificates. Specify a SSL mode of Verify CA or Verify full. Select the SSL certificate of the certificate authority (CA) of your database that you have previously uploaded with Wrangler. When creating the Hyperdrive configuration, Hyperdrive will attempt to connect to the database with the provided credentials. If the command provides successful results, you have properly configured your Hyperdrive configuration to verify the certificates provided by your database server. :::note Hyperdrive will attempt to connect to your database with the provided credentials to verify they are correct before creating a configuration. If you encounter an error when attempting to connect, refer to Hyperdrive's troubleshooting documentation to debug possible causes. ::: Client certificates Your database can be configured to verify a certificate provided by the client (in this case, Hyperdrive). This serves as an additional factor to authenticate clients (in addition to the username and password). Refer to the PostgreSQL or MySQL documentation for more details. For the database server to be able to verify the client certificates, Hyperdrive must be configured to provide a certificate file ( client-cert.pem) and a private key with which the certificate was generated ( private-key.pem). Step 1: Upload your client certificates (mTLS certificates) Upload your client certificates to be used by Hyperdrive using Wrangler: # requires Wrangler 4.9.0 or greater npx wrangler cert upload mtls-certificate --cert client-cert.pem --key client-key.pem --name --- Uploading client certificate ... Success! Uploaded client certificate ID: ... Step 2: Create a Hyperdrive configuration You can now create a Hyperdrive configuration using the newly created client certificate bundle using the dashboard or Wrangler. Using Wrangler, enter the following command in your terminal to create a Hyperdrive configuration with the client certificate pair: # PostgreSQL npx wrangler hyperdrive create --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" --mtls-certificate-id # MySQL npx wrangler hyperdrive create --connection-string="mysql://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name" --mtls-certificate-id From the dashboard, follow these steps to create a Hyperdrive configuration with server certificates: In the Cloudflare dashboard, go to the Hyperdrive page. Select Create configuration. Select Client certificates. Select the SSL client certificate and private key pair for Hyperdrive to use during the connection setup with your database server. When Hyperdrive connects to your database, it will provide a client certificate signed with the private key to the database server. This allows the database server to confirm that the client, in this case Hyperdrive, has both the private key and the client certificate. By using client certificates, you can add an additional authentication layer for your database to ensure that only Hyperdrive can connect to it. :::note Hyperdrive will attempt to connect to your database with the provided credentials to verify they are correct before creating a configuration. If you encounter an error when attempting to connect, refer to Hyperdrive's troubleshooting documentation to debug possible causes. ::: Tune connection pooling import { TabItem, Tabs, DashButton } from "~/components"; Hyperdrive maintains a pool of connections to your database that are shared across Worker invocations. You can configure the maximum number of these connections based on your database capacity and application requirements. :::note Hyperdrive does not have a limit on the number of concurrent client connections made from your Workers to Hyperdrive. Hyperdrive does have a limit of origin connections that can be made from Hyperdrive to your database. These are shared across Workers, with each Worker using one of these connections over the course of a database transaction. Refer to transaction pooling mode for more information. ::: Configure connection pool size You can configure the connection pool size using the Cloudflare dashboard, the Wrangler CLI, or the Cloudflare API. To configure connection pool size via the dashboard: Log in to the Cloudflare dashboard and select your account. Go to Storage & databases > Hyperdrive. Select your Hyperdrive configuration. Select Settings. In the Origin connection limit section, adjust the Maximum connections value. Select Save. Use the wrangler hyperdrive update command with the --origin-connection-limit flag: npx wrangler hyperdrive update --origin-connection-limit= Use the Hyperdrive REST API to update your configuration: curl --request PATCH \ --url https://api.cloudflare.com/client/v4/accounts//hyperdrive/configs/ \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer ' \ --data '{ "origin_connection_limit": }' All Hyperdrive configurations have a minimum of 5 connections. The maximum connection count depends on your Workers plan. :::note The Hyperdrive connection pool limit is a "soft limit". This means that it is possible for Hyperdrive to make more connections to your database than this limit in the event of network failure to ensure high availability. We recommend that you set the Hyperdrive connection limit to be lower than the limit of your origin database to account for occasions where Hyperdrive needs to create more connections for resiliency. ::: :::note You can request adjustments to Hyperdrive's origin connection limits. To request an increase, submit a Limit Increase Request and Cloudflare will contact you with next steps. Cloudflare also regularly monitors the Hyperdrive channel in Cloudflare's Discord community and can answer questions regarding limits and requests. ::: Best practices Start conservatively: Begin with a lower connection count and gradually increase it based on your application's performance. Monitor database metrics: Watch your database's connection usage and performance metrics to optimize the connection count. Consider database limits: Ensure your configured connection count does not exceed your database's maximum connection limit. Account for multiple configurations: If you have multiple Hyperdrive configurations connecting to the same database, consider the total connection count across all configurations. Related resources Connection pooling concepts Connection lifecycle Metrics and analytics Hyperdrive limits Query caching Examples import { DirectoryListing } from "~/components"; Python Workers import { Steps, Tabs, TabItem, WranglerConfig } from "~/components"; You can use Hyperdrive with Python Workers. To use Hyperdrive with Python Workers, set your compatibility date to 2026-09-08 or later. Supported drivers Hyperdrive in Python Workers uses TCP socket support to establish database connections. While you can use any Python driver that works with TCP connections, we strongly recommend using the drivers in the tables below, as they have been tested and verified to work with Hyperdrive. PostgreSQL Driver Documentation asyncpg (recommended) asyncpg documentation pg8000 pg8000 documentation psycopg psycopg documentation MySQL Driver Documentation aiomysql (recommended) aiomysql documentation pymysql pymysql documentation Connect to your database Before you begin, create a Python Worker and create a Hyperdrive configuration for your database. Add the Hyperdrive binding to your Wrangler configuration. Replace with your configuration ID. name = "python-hyperdrive" main = "src/main.py" compatibility_date = "$today" compatibility_flags = ["python_workers"] [[hyperdrive]] binding = "HYPERDRIVE" id = "" Install your driver and replace src/main.py with the corresponding example. [project] dependencies = [ "asyncpg", ] from contextlib import closing import asyncpg from workers import Response, WorkerEntrypoint class Default(WorkerEntrypoint): async def fetch(self, request): hd = self.env.HYPERDRIVE connection = await asyncpg.connect( host=hd.host, port=int(hd.port), user=hd.user, password=hd.password, database=hd.database, ssl=False, ) await connection.execute("SELECT 1") await connection.close() [project] dependencies = [ "aiomysql", ] import aiomysql from workers import Response, WorkerEntrypoint class Default(WorkerEntrypoint): async def fetch(self, request): hd = self.env.HYPERDRIVE connection = await aiomysql.connect( host=hd.host, port=int(hd.port), user=hd.user, password=hd.password, db=hd.database, ssl=None, ) try: cursor = await connection.cursor() await cursor.execute("SELECT 1") result = await cursor.fetchone() return Response.json({"result": result[0]}) finally: connection.close() Deploy your Worker: uv run pywrangler deploy Limitations and compatibility Socket support TCP socket support in Python Workers internally uses the connect API. While most standard library socket operations are supported, some low-level operations might not work as expected. Concurrency and async safety Socket operations in Python Workers do not block the event loop. Although Python's native socket operations are synchronous, the underlying TCP socket implementation in Python Workers is asynchronous. This allows multiple requests to be processed concurrently while one request waits for a socket operation to complete. To ensure synchronous database operations are serialized, use a lock to prevent concurrent access: import asyncio lock = asyncio.Lock() async with lock: # Your database operation here synchronous_db_operation() SQLAlchemy support Currently, only synchronous SQLAlchemy ORMs are supported in Python Workers. Async SQLAlchemy ORMs are not yet supported due to a lack of greenlet support in the Python Workers environment. Connect to MySQL import { TabItem, Tabs, Render, WranglerConfig } from "~/components"; Hyperdrive supports MySQL and MySQL-compatible databases, popular drivers, and Object Relational Mapper (ORM) libraries that use those drivers. Create a Hyperdrive :::note New to Hyperdrive? Refer to the Get started guide to learn how to set up your first Hyperdrive. ::: To create a Hyperdrive that connects to an existing MySQL database, use the Wrangler CLI or the Cloudflare dashboard. When using Wrangler, replace the placeholder value provided to --connection-string with the connection string for your database: # wrangler v3.11 and above required npx wrangler hyperdrive create my-first-hyperdrive --connection-string="mysql://user:password@database.host.example.com:3306/databasenamehere" The command above will output the ID of your Hyperdrive, which you will need to set in the Wrangler configuration file for your Workers project: This will allow Hyperdrive to generate a dynamic connection string within your Worker that you can pass to your existing database driver. Refer to Driver examples to learn how to set up a database driver with Hyperdrive. Refer to the Examples documentation for step-by-step guides on how to set up Hyperdrive with several popular database providers. Supported drivers Hyperdrive uses Workers TCP socket support to support TCP connections to databases. The following table lists the supported database drivers and the minimum version that works with Hyperdrive: Driver Documentation Minimum Version Required Notes mysql2 (recommended) mysql2 documentation mysql2@3.13.0 Supported in both Workers & Pages. Using the Promise API is recommended. mysql mysql documentation mysql@2.18.0 Requires compatibility_flags = ["nodejs_compat"] and compatibility_date = "2024-09-23" - refer to Node.js compatibility. Requires wrangler 3.78.7 or later. Drizzle Drizzle documentation Requires mysql2@3.13.0 Kysely Kysely documentation Requires mysql2@3.13.0 ^ The marked libraries can use either mysql or mysql2 as a dependency. Other drivers and ORMs not listed may also be supported: this list is not exhaustive. Database drivers and Node.js compatibility Node.js compatibility is required for database drivers, including mysql and mysql2, and needs to be configured for your Workers project. Supported TLS (SSL) modes Hyperdrive supports the following MySQL TLS/SSL connection modes when connecting to your origin database: Mode Supported Details DISABLED No Hyperdrive does not support insecure plain text connections. PREFERRED No (use REQUIRED) Hyperdrive will always use TLS. REQUIRED Yes (default) TLS is required, and server certificates are validated (based on WebPKI). VERIFY_CA Yes Verifies the server's TLS certificate is signed by a root CA on the client. VERIFY_IDENTITY Yes In addition to VERIFY_CA checks, Hyperdrive requires the database hostname to match a Subject Alternative Name (SAN) or Common Name (CN) on the certificate. Refer to SSL/TLS certificates documentation for details on how to configure VERIFY_CA or VERIFY_IDENTITY TLS (SSL) modes for Hyperdrive. Driver examples The following examples show you how to: Create a database client with a database driver. Pass the Hyperdrive connection string and connect to the database. Query your database via Hyperdrive. mysql2 The following Workers code shows you how to use mysql2 with Hyperdrive using the Promise API. mysql The following Workers code shows you how to use mysql with Hyperdrive. Identify connections from Hyperdrive To identify active connections to your MySQL database server from Hyperdrive: Hyperdrive's connections to your database will show up with Cloudflare Hyperdrive in the PROGRAM_NAME column in the performance_schema.threads table. Run SELECT DISTINCT USER, HOST, PROGRAM_NAME FROM performance_schema.threads WHERE PROGRAM_NAME = 'Cloudflare Hyperdrive' to show whether Hyperdrive is currently holding a connection (or connections) open to your database. Next steps Refer to the list of supported database integrations to understand other ways to connect to existing databases. Learn more about how to use the Socket API in a Worker. Understand the protocols supported by Workers. AWS RDS and Aurora import { Render } from "~/components"; This example shows you how to connect Hyperdrive to an Amazon Relational Database Service (Amazon RDS) or Amazon Aurora MySQL database instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. AWS Console When creating or modifying an instance in the AWS console: Configure a database cluster and other settings you wish to customize. Under Settings > Credential settings, note down the Master username and Master password (Aurora only). Under the Connectivity header, ensure Public access is set to Yes. Select an Existing VPC security group that allows public Internet access from 0.0.0.0/0 to the port your database instance is configured to listen on (default: 3306 for MySQL instances). Select Create database. :::caution You must ensure that the VPC security group associated with your database allows public IPv4 access to your database port. Refer to AWS' database server rules for details on how to configure rules specific to your RDS database. ::: Retrieve the database endpoint (Aurora) To retrieve the database endpoint (hostname) for Hyperdrive to connect to: Go to Databases view under RDS in the AWS console. Select the database you want Hyperdrive to connect to. Under the Endpoints header, note down the Endpoint name with the type Writer and the Port. Retrieve the database endpoint (RDS MySQL) For regular RDS instances (non-Aurora), you will need to fetch the endpoint and port of the database: Go to Databases view under RDS in the AWS console. Select the database you want Hyperdrive to connect to. Under the Connectivity & security header, note down the Endpoint and the Port. The endpoint will resemble YOUR_DATABASE_NAME.cpuo5rlli58m.AWS_REGION.rds.amazonaws.com, and the port will default to 3306. 2. Create your user Once your database is created, you will need to create a user for Hyperdrive to connect as. Although you can use the Master username configured during initial database creation, best practice is to create a less privileged user. To create a new user, log in to the database and use the CREATE USER command: # Log in to the database mysql -h ENDPOINT_NAME -P PORT -u MASTER_USERNAME -p database_name Run the following SQL statements: -- Create a role for Hyperdrive CREATE ROLE hyperdrive; -- Allow Hyperdrive to connect GRANT USAGE ON mysql_db.* TO hyperdrive; -- Grant database privileges to the hyperdrive role GRANT ALL PRIVILEGES ON mysql_db.* to hyperdrive; -- Create a specific user for Hyperdrive to log in as CREATE USER 'hyperdrive_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'sufficientlyRandomPassword'; -- Grant this new user the hyperdrive role privileges GRANT hyperdrive to 'hyperdrive_user'@'%'; Refer to AWS' documentation on user roles in MySQL for more details. With a database user, password, database endpoint (hostname and port), and database name, you can now set up Hyperdrive. 3. Create a database configuration Azure Database import { Render } from "~/components"; This example shows you how to connect Hyperdrive to an Azure Database for MySQL instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid credentials and network access. Azure Portal Public access networking To connect to your Azure Database for MySQL instance using public Internet connectivity: In the Azure Portal, select the instance you want Hyperdrive to connect to. Expand Settings > Networking > ensure Public access is enabled > in Firewall rules add 0.0.0.0 as Start IP address and 255.255.255.255 as End IP address. Select Save to persist your changes. Select Overview from the sidebar and note down the Server name of your instance. With the username, password, server name, and database name (default: mysql), you can now create a Hyperdrive database configuration. Private access networking To connect to a private Azure Database for MySQL instance, refer to Connect to a private database using Tunnel. 2. Create a database configuration Google Cloud SQL import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Google Cloud SQL MySQL database instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. Cloud Console When creating the instance or when editing an existing instance in the Google Cloud Console: To allow Hyperdrive to reach your instance: In the Cloud Console, select the instance you want Hyperdrive to connect to. Expand Connections > Networking > ensure Public IP is enabled > Add a Network and input 0.0.0.0/0. Select Done > Save to persist your changes. Select Overview from the sidebar and note down the Public IP address of your instance. To create a user for Hyperdrive to connect as: Select Users in the sidebar. Select Add User Account > select Built-in authentication. Provide a name (for example, hyperdrive-user), then select Generate to generate a password. Copy this password to your clipboard before selecting Add to create the user. With the username, password, public IP address and (optional) database name (default: mysql), you can now create a Hyperdrive database configuration. 2. Create a database configuration Database Providers import { DirectoryListing } from "~/components"; PlanetScale import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a PlanetScale MySQL database. Drizzle ORM import { Render, Steps } from "~/components"; Drizzle ORM is a lightweight TypeScript ORM with a focus on type safety. This example demonstrates how to use Drizzle ORM with MySQL via Cloudflare Hyperdrive in a Workers application. Prerequisites A Cloudflare account with Workers access A MySQL database A Hyperdrive configuration to your MySQL database 1. Install Drizzle Install the Drizzle ORM and its dependencies such as the mysql2 driver: # mysql2 v3.13.0 or later is required npm i drizzle-orm mysql2 dotenv npm i -D drizzle-kit tsx @types/node Add the required Node.js compatibility flags and Hyperdrive binding to your wrangler.jsonc file: 2. Configure Drizzle 2.1. Define a schema With Drizzle ORM, we define the schema in TypeScript rather than writing raw SQL. 1. Create a folder `/db/` in `/src/`. 2. Create a `schema.ts` file. 3. In `schema.ts`, define a `users` table as shown below. ```ts title="src/db/schema.ts" // src/schema.ts import { mysqlTable, int, varchar, timestamp } from "drizzle-orm/mysql-core"; export const users = mysqlTable("users", { id: int("id").primaryKey().autoincrement(), name: varchar("name", { length: 255 }).notNull(), email: varchar("email", { length: 255 }).notNull().unique(), createdAt: timestamp("created_at").defaultNow(), }); ``` 2.2. Connect Drizzle ORM to the database with Hyperdrive Use your the credentials of your Hyperdrive configuration for your database when using the Drizzle ORM. Populate your index.ts file as shown below. // src/index.ts import { drizzle } from "drizzle-orm/mysql2"; import { createConnection } from "mysql2/promise"; import { users } from "./db/schema"; export interface Env { HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create a connection using the mysql2 driver with the Hyperdrive credentials (only accessible from your Worker). const connection = await createConnection({ host: env.HYPERDRIVE.host, user: env.HYPERDRIVE.user, password: env.HYPERDRIVE.password, database: env.HYPERDRIVE.database, port: env.HYPERDRIVE.port, // Required to enable mysql2 compatibility for Workers disableEval: true, }); // Create the Drizzle client with the mysql2 driver connection const db = drizzle(connection); // Sample query to get all users const allUsers = await db.select().from(users); return Response.json(allUsers); }, } satisfies ExportedHandler; 2.3. Configure Drizzle-Kit for migrations (optional) :::note You need to set up the tables in your database so that Drizzle ORM can make queries that work. If you have already set it up (for example, if another user has applied the schema to your database), or if you are starting to use Drizzle ORM and the schema matches what already exists in your database, then you do not need to run the migration. ::: You can generate and run SQL migrations on your database based on your schema using Drizzle Kit CLI. Refer to Drizzle ORM docs for additional guidance. 1. Create a `.env` file in the root folder of your project, and add your database connection string. The Drizzle Kit CLI will use this connection string to create and apply the migrations. # .env # Replace with your direct database connection string DATABASE_URL='mysql://user:password@db-host.cloud/database-name' Create a drizzle.config.ts file in the root folder of your project to configure Drizzle Kit and add the following content: import 'dotenv/config'; import { defineConfig } from 'drizzle-kit'; export default defineConfig({ out: './drizzle', schema: './src/db/schema.ts', dialect: 'mysql', dbCredentials: { url: process.env.DATABASE_URL!, }, }); Generate the migration file for your database according to your schema files and apply the migrations to your database. npx drizzle-kit generate No config path provided, using default 'drizzle.config.ts' Reading config file 'drizzle.config.ts' Reading schema files: /src/db/schema.ts 1 tables users 4 columns 0 indexes 0 fks [✓] Your SQL migration file ➜ drizzle/0000_daffy_rhodey.sql 🚀 npx drizzle-kit migrate No config path provided, using default 'drizzle.config.ts' Reading config file 'drizzle.config.ts' 3. Deploy your Worker Deploy your Worker. npx wrangler deploy Libraries and Drivers import { DirectoryListing } from "~/components"; mysql import { Render } from "~/components"; The mysql package is a MySQL driver for Node.js. This example demonstrates how to use it with Cloudflare Workers and Hyperdrive. mysql2 import { Render } from "~/components"; The mysql2 package is a modern MySQL driver for Node.js with better performance and built-in Promise support. This example demonstrates how to use it with Cloudflare Workers and Hyperdrive. Connect to PostgreSQL import { TabItem, Tabs, Render, WranglerConfig } from "~/components"; Hyperdrive supports PostgreSQL and PostgreSQL-compatible databases, popular drivers and Object Relational Mapper (ORM) libraries that use those drivers. Create a Hyperdrive :::note New to Hyperdrive? Refer to the Get started guide to learn how to set up your first Hyperdrive. ::: To create a Hyperdrive that connects to an existing PostgreSQL database, use the wrangler CLI or the Cloudflare dashboard. When using wrangler, replace the placeholder value provided to --connection-string with the connection string for your database: # wrangler v3.11 and above required npx wrangler hyperdrive create my-first-hyperdrive --connection-string="postgres://user:password@database.host.example.com:5432/databasenamehere" The command above will output the ID of your Hyperdrive, which you will need to set in the Wrangler configuration file for your Workers project: This will allow Hyperdrive to generate a dynamic connection string within your Worker that you can pass to your existing database driver. Refer to Driver examples to learn how to set up a database driver with Hyperdrive. Refer to the Examples documentation for step-by-step guides on how to set up Hyperdrive with several popular database providers. Supported drivers Hyperdrive uses Workers TCP socket support to support TCP connections to databases. The following table lists the supported database drivers and the minimum version that works with Hyperdrive: Driver Documentation Minimum Version Required Notes node-postgres - pg (recommended) node-postgres - pg documentation pg@8.16.3 8.11.4 introduced a bug with URL parsing and will not work. 8.11.5 fixes this. Requires compatibility_flags = ["nodejs_compat"] and compatibility_date = "2024-09-23" - refer to Node.js compatibility. Requires wrangler 3.78.7 or later. Postgres.js Postgres.js documentation postgres@3.4.5 Supported in both Workers & Pages. Drizzle Drizzle documentation 0.26.2^ Kysely Kysely documentation 0.26.3^ rust-postgres rust-postgres documentation v0.19.8 Use the query_typed method for best performance. ^ The marked libraries use node-postgres as a dependency. Other drivers and ORMs not listed may also be supported: this list is not exhaustive. Database drivers and Node.js compatibility Node.js compatibility is required for database drivers, including Postgres.js, and needs to be configured for your Workers project. Driver examples The following examples show you how to: Create a database client with a database driver. Pass the Hyperdrive connection string and connect to the database. Query your database via Hyperdrive. node-postgres / pg Postgres.js Identify connections from Hyperdrive To identify active connections to your Postgres database server from Hyperdrive: Hyperdrive's connections to your database will show up with Cloudflare Hyperdrive as the application_name in the pg_stat_activity table. Run SELECT DISTINCT usename, application_name FROM pg_stat_activity WHERE application_name = 'Cloudflare Hyperdrive' to show whether Hyperdrive is currently holding a connection (or connections) open to your database. :::note Hyperdrive only sets the application_name to Cloudflare Hyperdrive when your driver does not send its own. Some drivers set a default application_name — for example, Postgres.js sends postgres.js unless you override it. Hyperdrive forwards the driver-provided value to your database, so those connections appear under that name (for example, postgres.js) instead of Cloudflare Hyperdrive. This does not mean the connection is bypassing Hyperdrive. To keep these connections identifiable as Hyperdrive, set the application_name explicitly in your driver. With Postgres.js: const sql = postgres(env.HYPERDRIVE.connectionString, { max: 5, fetch_types: false, connection: { application_name: "Cloudflare Hyperdrive", }, }); ::: Next steps Refer to the list of supported database integrations to understand other ways to connect to existing databases. Learn more about how to use the Socket API in a Worker. Understand the protocols supported by Workers. AWS RDS and Aurora import { Render } from "~/components"; This example shows you how to connect Hyperdrive to an Amazon Relational Database Service (Amazon RDS) Postgres or Amazon Aurora database instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. AWS Console When creating or modifying an instance in the AWS console: Configure a DB cluster identifier and other settings you wish to customize. Under Settings > Credential settings, note down the Master username and Master password (Aurora only). Under the Connectivity header, ensure Public access is set to Yes. Select an Existing VPC security group that allows public Internet access from 0.0.0.0/0 to the port your database instance is configured to listen on (default: 5432 for PostgreSQL instances). Select Create database. :::caution You must ensure that the VPC security group associated with your database allows public IPv4 access to your database port. Refer to AWS' database server rules for details on how to configure rules specific to your RDS or Aurora database. ::: Retrieve the database endpoint (Aurora) To retrieve the database endpoint (hostname) for Hyperdrive to connect to: Go to Databases view under RDS in the AWS console. Select the database you want Hyperdrive to connect to. Under the Endpoints header, note down the Endpoint name with the type Writer and the Port. Retrieve the database endpoint (RDS PostgreSQL) For regular RDS instances (non-Aurora), you will need to fetch the endpoint and port of the database: Go to Databases view under RDS in the AWS console. Select the database you want Hyperdrive to connect to. Under the Connectivity & security header, note down the Endpoint and the Port. The endpoint will resemble YOUR_DATABASE_NAME.cpuo5rlli58m.AWS_REGION.rds.amazonaws.com and the port will default to 5432. 2. Create your user Once your database is created, you will need to create a user for Hyperdrive to connect as. Although you can use the Master username configured during initial database creation, best practice is to create a less privileged user. To create a new user, log in to the database and use the CREATE ROLE command: # Log in to the database psql postgresql://MASTER_USERNAME:MASTER_PASSWORD@ENDPOINT_NAME:PORT/database_name Run the following SQL statements: -- Create a role for Hyperdrive CREATE ROLE hyperdrive; -- Allow Hyperdrive to connect GRANT CONNECT ON DATABASE postgres TO hyperdrive; -- Grant database privileges to the hyperdrive role GRANT ALL PRIVILEGES ON DATABASE postgres to hyperdrive; -- Create a specific user for Hyperdrive to log in as CREATE ROLE hyperdrive_user LOGIN PASSWORD 'sufficientlyRandomPassword'; -- Grant this new user the hyperdrive role privileges GRANT hyperdrive to hyperdrive_user; Refer to AWS' documentation on user roles in PostgreSQL for more details. With a database user, password, database endpoint (hostname and port) and database name (default: postgres), you can now set up Hyperdrive. 3. Create a database configuration Azure Database import { Render } from "~/components"; This example shows you how to connect Hyperdrive to an Azure Database for PostgreSQL instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid credentials and network access. Azure Portal Public access networking To connect to your Azure Database for PostgreSQL instance using public Internet connectivity: In the Azure Portal, select the instance you want Hyperdrive to connect to. Expand Settings > Networking > ensure Public access is enabled > in Firewall rules add 0.0.0.0 as Start IP address and 255.255.255.255 as End IP address. Select Save to persist your changes. Select Overview from the sidebar and note down the Server name of your instance. With the username, password, server name, and database name (default: postgres), you can now create a Hyperdrive database configuration. Private access networking To connect to a private Azure Database for PostgreSQL instance, refer to Connect to a private database using Tunnel. 2. Create a database configuration ClickHouse Managed Postgres import { PackageManagers, Render, Steps } from "~/components"; This example connects Hyperdrive to a ClickHouse Managed Postgres database in ClickHouse Cloud. ClickHouse Managed Postgres is a managed PostgreSQL service with local NVMe storage and built-in ClickHouse integration for analytics. :::note ClickHouse documents the platform availability and current product status of ClickHouse Managed Postgres. For details, refer to the ClickHouse Managed Postgres documentation. ::: Prerequisites Before you begin, you need: An existing ClickHouse Managed Postgres instance. A Workers project. Refer to Get started to create one. Wrangler version 4.9.0 or later, authenticated with your Cloudflare account. 1. Get your connection details In the ClickHouse Cloud console, select your Postgres instance and open the Connect menu. Select Directly to use the direct PostgreSQL endpoint. Hyperdrive provides connection pooling. Copy the hostname, port, database name, username, and password. Use a database role with the permissions your application needs. In Settings, download the certificate authority (CA) certificate for this instance. Save it locally as postgres-ca.pem. For more information, refer to ClickHouse Managed Postgres connection details. Your database must accept connections from Hyperdrive. If you restrict inbound connections by IP address, allow the Cloudflare IP address ranges. 2. Create a database configuration Use the instance CA to verify the database server with Transport Layer Security (TLS). The CA certificate is specific to your Postgres instance. Upload the CA certificate to your Cloudflare account: Copy the certificate ID from the command output. Create a Hyperdrive configuration using that ID and your database connection details: Replace each placeholder with your values. Use the direct endpoint port, which defaults to 5432. Keep the password and command output private. Copy the Hyperdrive configuration ID from the output. Use this ID for the Worker binding in the next section. The verify-full mode validates the certificate and database hostname. Hyperdrive checks the connection when you create the configuration. For certificate configuration details, refer to SSL/TLS certificates. This example turns off query caching so reads reach Postgres. Connection pooling still applies. For workloads that can tolerate cached results, refer to Query caching. 3. Use Hyperdrive from your Worker To test the connection through Hyperdrive, deploy your Worker and request its URL. A successful response contains success: true and the query results. Next steps Configure local development. Review supported PostgreSQL features. Diagnose connection errors with Troubleshoot and debug. CockroachDB import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a CockroachDB database cluster. CockroachDB is a PostgreSQL-compatible distributed SQL database with strong consistency guarantees. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. CockroachDB Console The steps below assume you have an existing CockroachDB Cloud account and database cluster created. To create and/or fetch your database credentials: Go to the CockroachDB Cloud console and select the cluster you want Hyperdrive to connect to. Select SQL Users from the sidebar on the left, and select Add User. Enter a username (for example, `hyperdrive-user), and select Generate & Save Password. Note down the username and copy the password to a temporary location. To retrieve your database connection details: Go to the CockroachDB Cloud console and select the cluster you want Hyperdrive to connect to. Select Connect in the top right. Choose the user you created, for example, hyperdrive-user. Select the database, for example defaultdb. Select General connection string as the option. In the text box below, select Copy to copy the connection string. By default, the CockroachDB cloud enables connections from the public Internet ( 0.0.0.0/0). If you have changed these settings on an existing cluster, you will need to allow connections from the public Internet for Hyperdrive to connect. 2. Create a database configuration Digital Ocean import { Render, Steps } from "~/components"; This example shows you how to connect Hyperdrive to a Digital Ocean database instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. DigitalOcean Dashboard 1. Go to the DigitalOcean dashboard and select the database you wish to connect to. 2. Go to the **Overview** tab. 3. Under the **Connection Details** panel, select **Public network**. 4. On the dropdown menu, select **Connection string** > **show-password**. 5. Copy the connection string. With the connection string, you can now create a Hyperdrive database configuration. 2. Create a database configuration :::note If you see a DNS-related error, it is possible that the DNS for your vendor's database has not yet been propagated. Try waiting 10 minutes before retrying the operation. Refer to DigitalOcean support page for more information. ::: Fly import { Render, Steps } from "~/components"; This example shows you how to connect Hyperdrive to a Fly Postgres database instance. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing Fly database by: Allocating a public IP address to your Fly database instance Configuring an external service Deploying the configuration Obtain the connection string, which is used to connect the database to Hyperdrive. 1. Run the following command to [allocate a public IP address](https://fly.io/docs/postgres/connecting/connecting-external/#allocate-an-ip-address). ```txt fly ips allocate-v6 --app ``` :::note Cloudflare recommends using IPv6, but some Internet service providers may not support IPv6. In this case, [you can allocate an IPv4 address](https://fly.io/docs/postgres/connecting/connecting-with-flyctl/). ::: Configure an external service by modifying the contents of your fly.toml file. Run the following command to download the fly.toml file. fly config save --app Then, replace the services and services.ports section of the file with the following toml snippet: [[services]] internal_port = 5432 # Postgres instance protocol = "tcp" [[services.ports]] handlers = ["pg_tls"] port = 5432 Deploy the new configuration. Obtain the connection string, which is in the form of: ```txt postgres://{username}:{password}@{public-hostname}:{port}/{database}?options ``` 2. Create a database configuration Google Cloud SQL import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Google Cloud SQL Postgres database instance. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access. Cloud Console When creating the instance or when editing an existing instance in the Google Cloud Console: To allow Hyperdrive to reach your instance: In the Cloud Console, select the instance you want Hyperdrive to connect to. Expand Connections > Networking > ensure Public IP is enabled > Add a Network and input 0.0.0.0/0. Select Done > Save to persist your changes. Select Overview from the sidebar and note down the Public IP address of your instance. To create a user for Hyperdrive to connect as: Select Users in the sidebar. Select Add User Account > select Built-in authentication. Provide a name (for example, hyperdrive-user) > select Generate to generate a password. Copy this password to your clipboard before selecting Add to create the user. With the username, password, public IP address and (optional) database name (default: postgres), you can now create a Hyperdrive database configuration. gcloud CLI The gcloud CLI allows you to create a new user and enable Hyperdrive to connect to your database. Use gcloud sql to create a new user (for example, hyperdrive-user) with a strong password: gcloud sql users create hyperdrive-user --instance=YOUR_INSTANCE_NAME --password=SUFFICIENTLY_LONG_PASSWORD Run the following command to enable Internet access to your database instance: # If you have any existing authorized networks, ensure you provide those as a comma separated list. # The gcloud CLI will replace any existing authorized networks with the list you provide here. gcloud sql instances patch YOUR_INSTANCE_NAME --authorized-networks="0.0.0.0/0" Refer to Google Cloud's documentation for additional configuration options. 2. Create a database configuration Database Providers import { DirectoryListing } from "~/components"; Materialize import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Materialize database. Materialize is a Postgres-compatible streaming database that can automatically compute real-time results against your streaming data sources. 1. Allow Hyperdrive access To allow Hyperdrive to connect to your database, you will need to ensure that Hyperdrive has valid user credentials and network access to your database. Materialize Console :::note Read the Materialize Quickstart guide to set up your first database. The steps below assume you have an existing Materialize database ready to go. ::: You will need to create a new application user and password for Hyperdrive to connect with: Log in to the Materialize Console. Under the App Passwords section, select Manage app passwords. Select New app password and enter a name, for example, hyperdrive-user. Select Create Password. Copy the provided password: it will only be shown once. To retrieve the hostname and database name of your Materialize configuration: Select Connect in the sidebar of the Materialize Console. Select External tools. Copy the Host, Port and Database settings. With the username, app password, hostname, port and database name, you can now connect Hyperdrive to your Materialize database. 2. Create a database configuration Neon import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Neon Postgres database. Nile import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Nile PostgreSQL database instance. Nile is PostgreSQL re-engineered for multi-tenant applications. Nile's virtual tenant databases provide you with isolation, placement, insight, and other features for your tenant's data and embedding. Refer to Nile documentation to learn more. 1. Allow Hyperdrive access You can connect Cloudflare Hyperdrive to any Nile database in your workspace using its connection string - either with a new set of credentials, or using an existing set. Nile console To get a connection string from Nile console: Log in to Nile console, then select a database. On the left hand menu, click Settings (the bottom-most icon) and then select Connection. Select the PostgreSQL logo to show the connection string. Select "Generate credentials" to generate new credentials. Copy the connection string (without the "psql" part). You will have obtained a connection string similar to the following: postgres://0191c898-...:4d7d8b45-...@eu-central-1.db.thenile.dev:5432/my_database With the connection string, you can now create a Hyperdrive database configuration. 2. Create a database configuration pgEdge Cloud import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a pgEdge Postgres database. pgEdge Cloud provides easy deployment of fully-managed, fully-distributed, and secure Postgres. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing pgEdge database with the default user and password provided by pgEdge. pgEdge dashboard To retrieve your connection string from the pgEdge dashboard: Go to the pgEdge dashboard and select the database you wish to connect to. From the Connect to your database section, note down the connection string (starting with postgres://app@...) from the Connection String text box. 2. Create a database configuration PlanetScale import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a PlanetScale PostgreSQL database. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing PlanetScale PostgreSQL database by creating a new role (optional) and retrieving a connection string to your database. PlanetScale Dashboard Go to the PlanetScale dashboard and select the database you wish to connect to. Click Connect. Create a new role for your Hyperdrive configuration (recommended): Ensure the minimum required permissions for Hyperdrive to read and write data to your tables: pg_read_all_data: Read data from all tables, views, and sequences pg_write_all_data: Write data to all tables, views, and sequences Click Create role. Note the user, the password, the database host, and the database name (or postgres as the default database). You will need these to create a database configuration in Hyperdrive. With the host, database name, username and password, you can now create a Hyperdrive database configuration. 2. Create a database configuration :::note When connecting to a PlanetScale PostgreSQL database with Hyperdrive, you should use a driver like node-postgres (pg) or Postgres.js to connect directly to the underlying database instead of the PlanetScale serverless driver. Hyperdrive is optimized for database access for Workers and will perform global connection pooling and fast query routing by connecting directly to your database. ::: Prisma Postgres import { Render, TabItem, Tabs, Steps } from "~/components"; This example shows you how to connect Hyperdrive to a Prisma Postgres database. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing Prisma Postgres database by using your existing database connection string. Prisma Data Platform Go to the Prisma Data Platform Console and select the project (database) you wish to connect to. Select Connect to your database > Any client. Select Generate database credentials. Copy the connection string for your Prisma Postgres database. Edit the connection string to make it compatible with Hyperdrive. Add the database name after the port. You may remove any query parameters, such as ?sslmode=require. The final string will look like: postgres://USERNAME:PASSWORD@HOSTNAME_OR_IP_ADDRESS:PORT/database_name ``` :::note An alternative to the Prisma Data Platform is to use the [`create-db`](https://www.npmjs.com/package/create-db) package. This package will generate a quick temporary Prisma Postgres database for you to use. ```bash npx create-db@latest ::: With this connection string, you can now create a Hyperdrive database configuration. 2. Create a database configuration 4. Configure Hyperdrive maximum connections Prisma Postgres has limits on the number of direct connections that can be made to the database using Hyperdrive. Refer to Prisma Postgres limits. :::note There are two limits to consider here. Origin database's connection limit, set by the origin database provider. This is the maximum number of direct database connections that can be made to the origin database. Hyperdrive's origin connection limit, set by Hyperdrive. This is the maximum number of database connections that Hyperdrive can make to your origin database (in this case, Prisma Postgres). Hyperdrive's origin connection limit should be lower than the Prisma Postgres connection limit, since Hyperdrive's origin connection limit is a soft limit, and Hyperdrive may create more connections if there are network disruptions that prevent existing connections from being used. ::: From the Cloudflare Hyperdrive dashboard, select your newly created Hyperdrive configuration. Go to Settings. In Origin connection limit, select Edit Settings, and set your maximum connections to a number that is lower than your Prisma connection limit. Edit your existing Hyperdrive configuration with the --origin-connection-limit parameter: npx wrangler hyperdrive update --origin-connection-limit=10 Replace with your Hyperdrive configuration ID and set the connection limit to a number that is less than your Prisma connection limit. Verify the configuration change: npx wrangler hyperdrive get :::note When connecting to a Prisma Postgres database with Hyperdrive, you should use a driver like node-postgres (pg) or Postgres.js to connect directly to the underlying PostgreSQL database, instead of the Prisma Accelerate extension. Hyperdrive is optimized for database access for Workers, and connects directly to your database to perform global connection pooling and fast query routing. ::: Supabase import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Supabase Postgres database. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing Supabase database as the Postgres user which is set up during project creation. Alternatively, to create a new user for Hyperdrive, run these commands in the SQL Editor. CREATE ROLE hyperdrive_user LOGIN PASSWORD 'sufficientlyRandomPassword'; -- Here, you are granting it the postgres role. In practice, you want to create a role with lesser privileges. GRANT postgres to hyperdrive_user; The database endpoint can be found in the database settings page. With a database user, password, database endpoint (hostname and port) and database name (default: postgres), you can now set up Hyperdrive. :::note When connecting to Supabase from Hyperdrive, you should use the Direct connection connection string rather than the pooled connection strings. Hyperdrive will perform pooling of connections to ensure optimal access from Workers. ::: 2. Create a database configuration :::note When connecting to a Supabase database with Hyperdrive, you should use a driver like node-postgres (pg) or Postgres.js to connect directly to the underlying database instead of the Supabase JavaScript client. Hyperdrive is optimized for database access for Workers and will perform global connection pooling and fast query routing by connecting directly to your database. ::: Timescale import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Timescale time-series database. Timescale is built on PostgreSQL, and includes powerful time-series, event and analytics features. You can learn more about Timescale by referring to their Timescale services documentation. 1. Allow Hyperdrive access You can connect Hyperdrive to any existing Timescale database by creating a new user and fetching your database connection string. Timescale Dashboard :::note Similar to most services, Timescale requires you to reset the password associated with your database user if you do not have it stored securely. You should ensure that you do not break any existing clients if when you reset the password. ::: To retrieve your credentials and database endpoint in the Timescale Console: Select the service (database) you want Hyperdrive to connect to. Expand Connection info. Copy the Service URL. The Service URL is the connection string that Hyperdrive will use to connect. This string includes the database hostname, port number and database name. If you do not have your password stored, you will need to select Forgot your password? and set a new SCRAM password. Save this password, as Timescale will only display it once. You will end up with a connection string resembling the below: postgres://tsdbadmin:YOUR_PASSWORD_HERE@pn79dztyy0.xzhhbfensb.tsdb.cloud.timescale.com:31358/tsdb With the connection string, you can now create a Hyperdrive database configuration. 2. Create a database configuration Xata import { Render } from "~/components"; This example shows you how to connect Hyperdrive to a Xata PostgreSQL database instance. Drizzle ORM import { Render, Steps } from "~/components"; Drizzle ORM is a lightweight TypeScript ORM with a focus on type safety. This example demonstrates how to use Drizzle ORM with PostgreSQL via Cloudflare Hyperdrive in a Workers application. Prerequisites A Cloudflare account with Workers access A PostgreSQL database A Hyperdrive configuration to your PostgreSQL database 1. Install Drizzle Install the Drizzle ORM and its dependencies such as the node-postgres ( pg) driver: npm i drizzle-orm pg dotenv npm i -D drizzle-kit tsx @types/pg @types/node Add the required Node.js compatibility flags and Hyperdrive binding to your wrangler.jsonc file: 2. Configure Drizzle 2.1. Define a schema With Drizzle ORM, we define the schema in TypeScript rather than writing raw SQL. 1. Create a folder `/db/` in `/src/`. 2. Create a `schema.ts` file. 3. In `schema.ts`, define a `users` table as shown below. ```ts title="src/db/schema.ts" // src/db/schema.ts import { pgTable, serial, varchar, timestamp } from "drizzle-orm/pg-core"; export const users = pgTable("users", { id: serial("id").primaryKey(), name: varchar("name", { length: 255 }).notNull(), email: varchar("email", { length: 255 }).notNull().unique(), createdAt: timestamp("created_at").defaultNow(), }); ``` 2.2. Connect Drizzle ORM to the database with Hyperdrive Use your Hyperdrive configuration for your database when using the Drizzle ORM. Populate your index.ts file as shown below. // src/index.ts import { Client } from "pg"; import { drizzle } from "drizzle-orm/node-postgres"; import { users } from "./db/schema"; export interface Env { HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create a new client instance for each request. const client = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); // Connect to the database await client.connect(); // Create the Drizzle client with the node-postgres connection const db = drizzle(client); // Sample query to get all users const allUsers = await db.select().from(users); return Response.json(allUsers); }, } satisfies ExportedHandler; :::note Use node-postgres with Drizzle ORM when connecting through Hyperdrive. ::: :::caution[Known issue with Postgres.js] Pairing Drizzle ORM with the Postgres.js driver over Hyperdrive is not currently supported. Switch your driver to node-postgres ( pg), the recommended driver for Drizzle ORM with Hyperdrive. ::: 2.3. Configure Drizzle-Kit for migrations (optional) :::note You need to set up the tables in your database so that Drizzle ORM can make queries that work. If you have already set it up (for example, if another user has applied the schema to your database), or if you are starting to use Drizzle ORM and the schema matches what already exists in your database, then you do not need to run the migration. ::: You can generate and run SQL migrations on your database based on your schema using Drizzle Kit CLI. Refer to Drizzle ORM docs for additional guidance. 1. Create a `.env` file the root folder of your project, and add your database connection string. The Drizzle Kit CLI will use this connection string to create and apply the migrations. # .env # Replace with your direct database connection string DATABASE_URL='postgres://user:password@db-host.cloud/database-name' Create a drizzle.config.ts file in the root folder of your project to configure Drizzle Kit and add the following content: // drizzle.config.ts import "dotenv/config"; import { defineConfig } from "drizzle-kit"; export default defineConfig({ out: "./drizzle", schema: "./src/db/schema.ts", dialect: "postgresql", dbCredentials: { url: process.env.DATABASE_URL!, }, }); Generate the migration file for your database according to your schema files and apply the migrations to your database. Run the following two commands: npx drizzle-kit generate No config path provided, using default 'drizzle.config.ts' Reading config file 'drizzle.config.ts' 1 tables users 4 columns 0 indexes 0 fks [✓] Your SQL migration file ➜ drizzle/0000_mysterious_queen_noir.sql 🚀 npx drizzle-kit migrate No config path provided, using default 'drizzle.config.ts' Reading config file 'drizzle.config.ts' Using 'postgres' driver for database querying 3. Deploy your Worker Deploy your Worker. npx wrangler deploy Libraries and Drivers import { DirectoryListing } from "~/components"; node-postgres (pg) import { Render } from "~/components"; node-postgres (pg) is a widely-used PostgreSQL driver for Node.js applications. This example demonstrates how to use node-postgres with Cloudflare Hyperdrive in a Workers application. Postgres.js import { Render } from "~/components"; Postgres.js is a modern, fully-featured PostgreSQL driver for Node.js. This example demonstrates how to use Postgres.js with Cloudflare Hyperdrive in a Workers application. Prisma ORM import { Render, Steps, PackageManagers } from "~/components"; Prisma ORM is a Node.js and TypeScript ORM with a focus on type safety and developer experience. This example demonstrates how to use Prisma ORM with PostgreSQL via Cloudflare Hyperdrive in a Workers application. Prerequisites A Cloudflare account with Workers access A PostgreSQL database (such as Prisma Postgres) A Hyperdrive configuration to your PostgreSQL database An existing Worker project 1. Install Prisma ORM Install Prisma CLI as a dev dependency: Install the pg driver and Prisma driver adapter for use with Hyperdrive: If using TypeScript, install the types package: Add the required Node.js compatibility flags and Hyperdrive binding to your Wrangler configuration file: 2. Configure Prisma ORM 2.1. Initialize Prisma Initialize Prisma in your application: npx prisma init This creates a prisma folder with a schema.prisma file and an .env file. 2.2. Define a schema Define your database schema in the prisma/schema.prisma file: generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) name String email String @unique createdAt DateTime @default(now()) } 2.3. Set up environment variables Add your database connection string to the .env file created by Prisma: DATABASE_URL="postgres://user:password@host:port/database" Add helper scripts to your package.json: "scripts": { "migrate": "npx prisma migrate dev", "generate": "npx prisma generate --no-engine", "studio": "npx prisma studio" } 2.4. Generate Prisma Client Generate the Prisma client with driver adapter support: npm run generate 2.5. Run migrations Generate and apply the database schema: npm run migrate When prompted, provide a name for the migration (for example, init). 3. Connect Prisma ORM to Hyperdrive Use your Hyperdrive configuration when using Prisma ORM. Update your src/index.ts file: import { PrismaPg } from "@prisma/adapter-pg"; import { PrismaClient } from "@prisma/client"; export interface Env { HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create Prisma client using driver adapter with Hyperdrive connection string const adapter = new PrismaPg({ connectionString: env.HYPERDRIVE.connectionString }); const prisma = new PrismaClient({ adapter }); // Sample query to create and fetch users const user = await prisma.user.create({ data: { name: "John Doe", email: `john.doe.${Date.now()}@example.com`, }, }); const allUsers = await prisma.user.findMany(); return Response.json({ newUser: user, allUsers: allUsers, }); }, } satisfies ExportedHandler; :::note When using Prisma ORM with Hyperdrive, you must use driver adapters to properly utilize the Hyperdrive connection string. The @prisma/adapter-pg driver adapter allows Prisma ORM to work with the pg driver and Hyperdrive's connection pooling. This approach provides connection pooling at the network level through Hyperdrive, so you don't need Prisma-specific connection pooling extensions like Prisma Accelerate. ::: 4. Deploy your Worker Deploy your Worker: npx wrangler deploy Observability import { DirectoryListing } from "~/components"; Metrics and analytics import { DashButton } from "~/components"; Hyperdrive exposes analytics that allow you to inspect query volume, query latency, cache hit ratios, and connection pool metrics for each Hyperdrive configuration in your account. Metrics Hyperdrive currently exports metrics via the hyperdriveQueriesAdaptiveGroups and hyperdrivePoolSizesAdaptiveGroups GraphQL datasets. Query metrics The hyperdriveQueriesAdaptiveGroups dataset contains the following metrics: Metric GraphQL Field Name Description Queries count The number of queries issued against your Hyperdrive in the given time period. Cache Status cacheStatus Whether the query was cached or not. Can be one of disabled, hit, miss, uncacheable, multiplestatements, notaquery, oversizedquery, oversizedresult, parseerror, transaction, and volatile. Query Bytes queryBytes The size of your queries, in bytes. Result Bytes resultBytes The size of your query results, in bytes. Connection Latency connectionLatency The time (in milliseconds) required to establish new connections from Hyperdrive to your database, as measured from your Hyperdrive connection pool(s). Query Latency queryLatency The time (in milliseconds) required to query (and receive results) from your database, as measured from your Hyperdrive connection pool(s). Event Status eventStatus Whether a query responded successfully ( complete) or failed ( error). The volatile cache status indicates the query contains a PostgreSQL function categorized as STABLE or VOLATILE (for example, NOW(), RANDOM()). Refer to Query caching for details on which functions affect cacheability. Pool size metrics The hyperdrivePoolSizesAdaptiveGroups dataset contains the following connection pool metrics: Metric GraphQL Field Name Description Avg. open connections avg.currentPoolSize Average number of connections currently open in the pool. Avg. available slots avg.availablePoolSlots Average number of pool connections available for checkout. Avg. waiting clients avg.waitingClients Average number of clients waiting for a connection from the pool. Pool size maximum max.maxPoolSize Configured maximum size of the connection pool. Peak open connections max.currentPoolSize Peak number of connections open in the pool. Peak waiting clients max.waitingClients Peak number of clients waiting for a connection from the pool. Connection contention appears as a spike in waiting clients, or when open connections consistently approach the pool size maximum. If your open connections regularly approach this limit, consider increasing your Hyperdrive connection limit. Metrics can be queried (and are retained) for the past 31 days. View metrics in the dashboard Per-database analytics for Hyperdrive are available in the Cloudflare dashboard. To view current and historical metrics for a Hyperdrive configuration: In the Cloudflare dashboard, go to the Hyperdrive page. Select an existing Hyperdrive configuration. Select the Metrics tab. You can optionally select a time window to query. This defaults to the last 24 hours. The dashboard includes a Pool connections chart, which displays waiting connections, open connections, and the pool size maximum. You can use the location selector to filter by specific Cloudflare locations. Query via the GraphQL API You can programmatically query analytics for your Hyperdrive configurations via the GraphQL Analytics API. This API queries the same datasets as the Cloudflare dashboard, and supports GraphQL introspection. Hyperdrive's GraphQL datasets require an accountTag filter with your Cloudflare account ID. Hyperdrive exposes the hyperdriveQueriesAdaptiveGroups and hyperdrivePoolSizesAdaptiveGroups datasets. Write GraphQL queries Examples of how to explore your Hyperdrive metrics. Get the number of queries handled via your Hyperdrive config by cache status query HyperdriveQueries( $accountTag: string! $configId: string! $datetimeStart: Time! $datetimeEnd: Time! ) { viewer { accounts(filter: { accountTag: $accountTag }) { hyperdriveQueriesAdaptiveGroups( limit: 10000 filter: { configId: $configId datetime_geq: $datetimeStart datetime_leq: $datetimeEnd } ) { count dimensions { cacheStatus } } } } } Get the average query and connection latency for queries handled via your Hyperdrive config within a range of time, excluding queries that failed due to an error query AverageHyperdriveLatencies( $accountTag: string! $configId: string! $datetimeStart: Time! $datetimeEnd: Time! ) { viewer { accounts(filter: { accountTag: $accountTag }) { hyperdriveQueriesAdaptiveGroups( limit: 10000 filter: { configId: $configId eventStatus: "complete" datetime_geq: $datetimeStart datetime_leq: $datetimeEnd } ) { avg { connectionLatency queryLatency } } } } } Get the total amount of query and result bytes flowing through your Hyperdrive config query HyperdriveQueryAndResultBytesForSuccessfulQueries( $accountTag: string! $configId: string! $datetimeStart: Date! $datetimeEnd: Date! ) { viewer { accounts(filter: { accountTag: $accountTag }) { hyperdriveQueriesAdaptiveGroups( limit: 10000 filter: { configId: $configId datetime_geq: $datetimeStart datetime_leq: $datetimeEnd } ) { sum { queryBytes resultBytes } } } } } Get the pool size metrics for your Hyperdrive config query HyperdrivePoolSizes( $accountTag: string! $configId: string! $datetimeStart: Time! $datetimeEnd: Time! ) { viewer { accounts(filter: { accountTag: $accountTag }) { hyperdrivePoolSizesAdaptiveGroups( limit: 10000 filter: { configId: $configId datetime_geq: $datetimeStart datetime_leq: $datetimeEnd } ) { avg { currentPoolSize availablePoolSlots waitingClients } max { maxPoolSize currentPoolSize waitingClients } dimensions { coloCode } } } } } Troubleshoot and debug Troubleshoot and debug errors commonly associated with connecting to a database with Hyperdrive. Configuration errors When creating a new Hyperdrive configuration, or updating the connection parameters associated with an existing configuration, Hyperdrive performs a test connection to your database in the background before creating or updating the configuration. Hyperdrive will also issue an empty test query, a ; in PostgreSQL, to validate that it can pass queries to your database. Error Code Details Recommended fixes 2008 Bad hostname. Hyperdrive could not resolve the database hostname. Confirm it exists in public DNS. 2009 The hostname does not resolve to a public IP address, or the IP address is not a public address. Hyperdrive can only connect to public IP addresses. Private IP addresses, like 10.1.5.0 or 192.168.2.1, are not currently supported. 2010 Cannot connect to the host:port. Hyperdrive could not route to the hostname: ensure it has a public DNS record that resolves to a public IP address. Check that the hostname is not misspelled. 2011 Connection refused. A network firewall or access control list (ACL) is likely rejecting requests from Hyperdrive. Ensure you have allowed connections from the public Internet. 2012 TLS (SSL) not supported by the database. Hyperdrive requires TLS (SSL) to connect. Configure TLS on your database. 2013 Invalid database credentials. Ensure your username is correct (and exists), and the password is correct (case-sensitive). 2014 The specified database name does not exist. Check that the database (not table) name you provided exists on the database you are asking Hyperdrive to connect to. 2015 Generic error. Hyperdrive failed to connect and could not determine a reason. Open a support ticket so Cloudflare can investigate. 2016 Test query failed. Confirm that the user Hyperdrive is connecting as has permissions to issue read and write queries to the given database. Failure to connect Hyperdrive may also emit Failed to connect to the provided database when it fails to connect to the database when attempting to create a Hyperdrive configuration. This is possible when the TLS (SSL) certificates are misconfigured. Here is a non-exhaustive table of potential failure to connect errors: Error message Details Recommended fixes Server return error and closed connection. This message occurs when you attempt to connect to a database that has client certificate verification enabled. Ensure you are configuring your Hyperdrive with client certificates if your database requires them. TLS handshake failed: cert validation failed. This message occurs when Hyperdrive has been configured with server CA certificates and is indicating that the certificate provided by the server has not been signed by the expected CA certificate. Ensure you are using the correct CA certificate for Hyperdrive, or ensure you are connecting to the right database. Connection errors Hyperdrive may also return errors at runtime. This can happen during initial connection setup, or in response to a query or other wire-protocol command sent by your driver. These errors are returned as ErrorResponse wire protocol messages, which are handled by most drivers by throwing from the responsible query or by triggering an error event. Hyperdrive errors that do not map 1:1 with an error message code documented by PostgreSQL use the 58000 error code. Hyperdrive may also encounter ErrorResponse wire protocol messages sent by your database. Hyperdrive will pass these errors through unchanged when possible. Hyperdrive specific errors Error Message Details Recommended fixes Internal error. Something is broken on our side. Check for an ongoing incident affecting Hyperdrive, and contact Cloudflare Support. Retrying the query is appropriate, if it makes sense for your usage pattern. Failed to acquire a connection from the pool. Hyperdrive timed out while waiting for a connection to your database, or cannot connect at all. If you are seeing this error intermittently, your Hyperdrive pool is being exhausted because too many connections are being held open for too long by your worker. This can be caused by a myriad of different issues, but long-running queries/transactions are a common offender. Server connection attempt failed: connection_refused Hyperdrive is unable to create new connections to your origin database. A network firewall or access control list (ACL) is likely rejecting requests from Hyperdrive. Ensure you have allowed connections from the public Internet. Sometimes, this can be caused by your database host provider refusing incoming connections when you go over your connection limit. Hyperdrive does not currently support MySQL COM_STMT_PREPARE messages Hyperdrive does not support prepared statements for MySQL databases. Remove prepared statements from your MySQL queries. Node errors Error Message Details Recommended fixes Uncaught Error: No such module "node:" Your Cloudflare Workers project or a library that it imports is trying to access a Node module that is not available. Enable Node.js compatibility for your Cloudflare Workers project to maximize compatibility. Stale reads after writes If your application writes data and then a later read returns older data, Hyperdrive query caching may be serving a cached read query result. Check Hyperdrive metrics by cacheStatus to confirm whether reads return hit, miss, disabled, or uncacheable. Refer to Metrics and analytics. To resolve stale reads after writes, refer to Query caching for guidance on splitting fresh reads from cacheable reads, including using a cache-disabled Hyperdrive configuration for reads that must return fresh data. Uncached queries If your queries are not being cached despite Hyperdrive having caching enabled, check the following: Stable or volatile PostgreSQL functions in your query: Queries that contain PostgreSQL functions categorized as STABLE or VOLATILE are not cacheable. Common examples include NOW(), CURRENT_TIMESTAMP, CURRENT_DATE, RANDOM(), and LASTVAL(). To resolve this, move the function call to your application code and pass the result as a query parameter. For example, instead of WHERE created_at > NOW(), compute the timestamp in your Worker and pass it as a parameter: WHERE created_at > $1. Refer to Query caching for a full list of uncacheable functions. Function names in SQL comments: Hyperdrive uses text-based pattern matching to detect some uncacheable functions. References to function names like NOW() in SQL comments can cause the query to be treated as uncacheable, even if the function is not actually called. Remove references to uncacheable function names from query text, including comments. Driver configuration: Your driver may be configured such that your queries are not cacheable by Hyperdrive. This may happen if you are using the Postgres.js driver with prepare: false. To resolve this, enable prepared statements with prepare: true. Driver errors Error Message Details Recommended fixes Code generation from strings disallowed for this context The database driver you are using is attempting to use the eval() command, which is unsupported on Cloudflare Workers (common in mysql2 driver). Configure the database driver to not use eval(). See how to configure mysql2 to disable the usage of eval(). Stale connection and I/O context errors These errors occur when a database client or connection is created in the global scope (outside of a request handler) or is reused across requests. Workers do not allow I/O across requests, and database connections from a previous request context become unusable. Always create database clients inside your handlers. Workers runtime errors Error Message Details Recommended fixes Disallowed operation called within global scope. Asynchronous I/O (ex: fetch() or connect()), setting a timeout, and generating random values are not allowed within global scope. Your Worker is attempting to open a database connection or perform I/O during script startup, outside of a request handler. Move the database client creation into your fetch, queue, or other handler function. Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler. A database connection or client created during one request is being reused in a subsequent request. Create a new database client on every request instead of caching it in a global variable. Hyperdrive's connection pooling already eliminates the connection startup overhead. node-postgres ( pg) errors Error Message Details Recommended fixes Connection terminated The client's .end() method was called, or the connection was cleaned up at the end of a previous request. Create a new Client inside your handler instead of reusing one from a prior request. Connection terminated unexpectedly The underlying connection was dropped without an explicit .end() call — for example, when a previous request's context was garbage collected. Create a new Client inside your handler for every request. Client has encountered a connection error and is not queryable A socket-level error occurred on the connection (common when reusing a client across requests). Create a new Client inside your handler. Do not store clients in global variables. Client was closed and is not queryable A query was attempted on a client whose .end() method was already called. Create a new Client inside your handler instead of reusing one. Cannot use a pool after calling end on the pool pool.connect() was called on a Pool instance that has already been ended. Do not use new Pool() in the global scope. Create a new Client() inside your handler — Hyperdrive handles connection pooling for you. Client has already been connected. You cannot reuse a client. client.connect() was called on a client that was already connected in a previous invocation. Create a new Client per request. node-postgres clients cannot be reconnected once connected. Postgres.js ( postgres) errors Postgres.js error messages include the error code and the target host. The code property on the error object contains the error code. Error Message Details Recommended fixes write CONNECTION_ENDED : A query was attempted after sql.end() was called, or the connection was cleaned up from a prior request. Error code: CONNECTION_ENDED. Create a new postgres() instance inside your handler. write CONNECTION_DESTROYED : The connection was forcefully terminated — for example, during sql.end({ timeout }) expiration, or because the connection was already terminated. Error code: CONNECTION_DESTROYED. Create a new postgres() instance inside your handler for every request. write CONNECTION_CLOSED : The underlying socket was closed unexpectedly while queries were still pending. Error code: CONNECTION_CLOSED. Create a new postgres() instance inside your handler. If this occurs within a single request, check for network issues or query timeouts. mysql2 errors Error Message Details Recommended fixes Can't add new command when connection is in closed state A query was attempted on a connection that has already been closed or encountered a fatal error. Create a new connection inside your handler instead of reusing one from global scope. Connection lost: The server closed the connection. The underlying socket was closed by the server or was garbage collected between requests. Error code: PROTOCOL_CONNECTION_LOST. Create a new connection inside your handler for every request. Pool is closed. pool.getConnection() was called on a pool that has already been closed. Do not use createPool() in the global scope. Create a new createConnection() inside your handler — Hyperdrive handles pooling for you. mysql errors Error Message Details Recommended fixes Cannot enqueue Query after fatal error. A query was attempted on a connection that previously encountered a fatal error. Error code: PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR. Create a new connection inside your handler instead of reusing one from global scope. Cannot enqueue Query after invoking quit. A query was attempted on a connection after .end() was called. Error code: PROTOCOL_ENQUEUE_AFTER_QUIT. Create a new connection inside your handler for every request. Cannot enqueue Handshake after already enqueuing a Handshake. .connect() was called on a connection that was already connected in a previous request. Error code: PROTOCOL_ENQUEUE_HANDSHAKE_TWICE. Create a new connection per request. mysql connections cannot be reconnected once connected. Improve performance Having query traffic written as transactions can limit performance. This is because in the case of a transaction, the connection must be held for the duration of the transaction, which limits connection multiplexing. If there are multiple queries per transaction, this can be particularly impactful on connection multiplexing. Where possible, we recommend not wrapping queries in transactions to allow the connections to be shared more aggressively. Platform import { DirectoryListing } from "~/components"; Limits The following limits apply to Hyperdrive configurations, connections, and queries made to your configured origin databases. Configuration limits These limits apply when creating or updating Hyperdrive configurations. Limit Free Paid Maximum configured databases 10 per account 25 per account Maximum username length [^1] 63 characters (bytes) 63 characters (bytes) Maximum database name length [^1] 63 characters (bytes) 63 characters (bytes) [^1]: This is a limit enforced by PostgreSQL. Some database providers may enforce smaller limits. Connection limits These limits apply to connections between Hyperdrive and your origin database. Limit Free Paid Initial connection timeout 15 seconds 15 seconds Idle connection timeout 10 minutes 10 minutes Maximum origin database connections (per configuration) [^2] ~20 connections ~100 connections Hyperdrive does not limit the number of concurrent client connections from your Workers. However, Hyperdrive limits connections to your origin database because most hosted databases have connection limits. [^2]: Hyperdrive is a distributed system, so a client may be unable to reach an existing pool. In this scenario, a new pool is established with its own connection allocation. This prioritizes availability over strict limit enforcement, which means connection counts may occasionally exceed the listed limits. Connection errors When Hyperdrive cannot acquire a connection to your origin database, you may see one of the following errors: Error message Cause Failed to acquire a connection from the pool. The connection pool is exhausted because connections are held open too long. Long-running queries or transactions are a common cause. Server connection attempt failed: connection_refused Your origin database is rejecting connections. This can occur when a firewall blocks Hyperdrive, or when your database provider's connection limit is exceeded. For a complete list of error codes, refer to Troubleshoot and debug. Query limits These limits apply to queries sent through Hyperdrive. Limit Free Paid Maximum query (statement) duration 60 seconds 60 seconds Maximum cached query response size 50 MB 50 MB Queries exceeding the maximum duration are terminated. Query responses larger than 50 MB are not cached but are still returned to your Worker. Request a limit increase You can request adjustments to limits that conflict with your project goals by contacting Cloudflare. Not all limits can be increased. To request an increase, submit a Limit Increase Request form. You can also ask questions in the Hyperdrive channel on Cloudflare's Discord community. Pricing import { Render } from "~/components"; Hyperdrive limits are automatically adjusted when subscribed to a Workers Paid plan. Hyperdrive's connection pooling and query caching are included in Workers Paid plan, so do not incur any additional charges. PlanetScale Postgres & MySQL You can create PlanetScale Postgres and MySQL databases from Cloudflare and bill PlanetScale database usage through your Cloudflare account as a pay-as-you-go customer. PlanetScale database usage is separate from Hyperdrive usage. When you create a PlanetScale database from the Cloudflare dashboard, PlanetScale usage appears on your Cloudflare invoice each billing period as a dollar total at PlanetScale's standard pricing. You can view per-database billing usage in the PlanetScale dashboard. To learn how PlanetScale databases work with Workers and Hyperdrive, refer to PlanetScale Postgres and MySQL with Hyperdrive. Pricing FAQ Does connection pooling or query caching incur additional charges? No. Hyperdrive's built-in cache and connection pooling are included within the stated plans above. There are no hidden limits other than those published. Are cached queries counted the same as uncached queries? Yes, any query made through Hyperdrive, whether cached or uncached, whether query or mutation, is counted according to the limits above. Does Hyperdrive charge for data transfer / egress? No. :::note For questions about pricing, refer to the pricing FAQs. ::: Release notes import { ProductReleaseNotes } from "~/components"; {/* */} FAQ Below you will find answers to our most commonly asked questions regarding Hyperdrive. Connectivity Does Hyperdrive use specific IP addresses to connect to my database? Hyperdrive connects to your database using Cloudflare's IP address ranges. These are shared by all Hyperdrive configurations and other Cloudflare products. You can use this to configure restrictions in your database firewall to restrict the IP addresses that can access your database. Does Hyperdrive support connecting to D1 databases? Hyperdrive does not support D1 because D1 provides fast connectivity from Workers by design. Hyperdrive is designed to speed up connectivity to traditional, regional SQL databases such as PostgreSQL. These databases are typically accessed using database drivers that communicate over TCP/IP. Unlike D1, creating a secure database connection to a traditional SQL database involves multiple round trips between the client (your Worker) and your database server. See How Hyperdrive works for more detail on why round trips are needed and how Hyperdrive solves this. D1 does not require round trips to create database connections. D1 is designed to be performant for access from Workers by default, without needing Hyperdrive. Should I use Placement with Hyperdrive? Yes, if your Worker makes multiple queries per request. Placement runs your Worker near your database, reducing per-query latency from 20-30ms to 1-3ms. Hyperdrive handles connection pooling and setup. Placement reduces the network distance for query execution. Use placement.region if your database runs in AWS, GCP, or Azure. Use placement.host for databases hosted elsewhere. Caching Does Hyperdrive invalidate cached reads when I write to my database No. Hyperdrive does not invalidate cached read query results when your application writes to your database. A matching read can return a cached result until the configured max_age expires, and Hyperdrive can serve that result during the stale_while_revalidate window while it refreshes the cache. Use a cache-disabled Hyperdrive configuration for reads that must return fresh data, such as authentication, sessions, permissions, or reads immediately after a write. Refer to Query caching to choose a caching strategy. Can I use Hyperdrive if some reads need read-after-write consistency Yes. Configure two Hyperdrive bindings to the same database: one with query caching enabled for reads that can tolerate short staleness, and one with query caching disabled for reads that must be fresh. The cache-disabled binding still gives you Hyperdrive's connection pooling and fast connection setup. If an object-relational mapping (ORM) library or authentication library owns the SQL, create separate database clients for each binding and pass the cache-disabled client to the code that needs fresh reads. Pricing Does Hyperdrive charge for data transfer / egress? No. Is Hyperdrive available on the Workers Free plan? Yes. Refer to pricing. Does Hyperdrive charge for additional compute? Hyperdrive itself does not charge for compute (CPU) or processing (wall clock) time. Workers querying Hyperdrive and computing results: for example, serializing results into JSON and/or issuing queries, are billed per Workers pricing. Limits Are there any limits to Hyperdrive? Refer to the published limits documentation. Reference import { DirectoryListing } from "~/components"; Supported databases and features The following table shows which database engines and/or specific database providers are supported. Database Engine Supported Known supported versions Details PostgreSQL ✅ 9.0 to 18.x Both self-hosted and managed (AWS, Azure, Google Cloud, Oracle) instances are supported. MySQL ✅ 5.7 to 8.x Both self-hosted and managed (AWS, Azure, Google Cloud, Oracle) instances are supported. MariaDB is also supported. SQL Server Not currently supported. MongoDB Not currently supported. Supported database providers Hyperdrive supports managed Postgres and MySQL databases provided by various providers, including AWS, Azure, and GCP. Refer to Examples to see how to connect to various database providers. Hyperdrive also supports databases that are compatible with the Postgres or MySQL protocol. The following is a non-exhaustive list of Postgres or MySQL-compatible database providers: Database Engine Supported Known supported versions Details AWS Aurora ✅ All Postgres-compatible and MySQL-compatible. Refer to AWS Aurora examples for MySQL and Postgres. ClickHouse Managed Postgres ✅ All Refer to the ClickHouse Managed Postgres guide to connect. Neon ✅ All Neon currently runs Postgres 15.x Supabase ✅ All Supabase currently runs Postgres 15.x Timescale ✅ All See the Timescale guide to connect. Materialize ✅ All Postgres-compatible. Refer to the Materialize guide to connect. CockroachDB ✅ All Postgres-compatible. Refer to the CockroachDB guide to connect. PlanetScale ✅ All PlanetScale provides MySQL-compatible and PostgreSQL databases MariaDB ✅ All MySQL-compatible. Supported TLS (SSL) modes PostgreSQL Hyperdrive supports the following PostgreSQL TLS (SSL) connection modes when connecting to your origin database: Mode Supported Details none No Hyperdrive does not support insecure plain text connections. prefer No (use require) Hyperdrive will always use TLS. require Yes (default) TLS is required, and server certificates are validated (based on WebPKI). verify-ca Yes Verifies the server's TLS certificate is signed by a root CA on the client. This ensures the server has a certificate the client trusts. verify-full Yes Identical to verify-ca, but also requires the database hostname must match a Subject Alternative Name (SAN) present on the certificate. MySQL Hyperdrive supports the following MySQL TLS (SSL) connection modes when connecting to your origin database: Mode Supported Details DISABLED No Hyperdrive does not support insecure plain text connections. PREFERRED No (use REQUIRED) Hyperdrive will always use TLS. REQUIRED Yes (default) TLS is required, and server certificates are validated (based on WebPKI). VERIFY_CA Yes Verifies the server's TLS certificate is signed by a root CA on the client. This ensures the server has a certificate the client trusts. VERIFY_IDENTITY Yes In addition to VERIFY_CA checks, Hyperdrive requires the database hostname to match a Subject Alternative Name (SAN) or Common Name (CN) on the certificate. Refer to SSL/TLS certificates documentation for details on how to configure these TLS (SSL) modes for Hyperdrive. Supported PostgreSQL authentication modes Hyperdrive supports the following authentication modes for connecting to PostgreSQL databases: Password Authentication ( md5) Password Authentication ( password) (clear-text password) SASL Authentication ( SCRAM-SHA-256) Unsupported PostgreSQL features: Hyperdrive does not support the following PostgreSQL features: SQL-level management of prepared statements, such as using PREPARE, DISCARD, DEALLOCATE, or EXECUTE. Advisory locks (PostgreSQL documentation). LISTEN and NOTIFY. PREPARE and DEALLOCATE. Any modification to per-session state not explicitly documented as supported elsewhere. Unsupported MySQL features: Hyperdrive does not support the following MySQL features: Non-UTF8 characters in queries USE statements Multi-statement queries Prepared statement queries via SQL (using PREPARE and EXECUTE statements) and protocol-level prepared statements. COM_INIT_DB messages Authentication plugins other than caching_sha2_password or mysql_native_password In cases where you need to issue these unsupported statements from your application, the Hyperdrive team recommends setting up a second, direct client without Hyperdrive. Wrangler commands import { WranglerNamespace } from "~/components"; The following Wrangler commands apply to Hyperdrive. Tutorials import { GlossaryTooltip, ListTutorials } from "~/components" View tutorials to help you get started with Hyperdrive. Create a serverless, globally distributed time-series API with Timescale import { Render, PackageManagers, WranglerConfig } from "~/components"; In this tutorial, you will learn to build an API on Workers which will ingest and query time-series data stored in Timescale (they make PostgreSQL faster in the cloud). You will create and deploy a Worker function that exposes API routes for ingesting data, and use Hyperdrive to proxy your database connection from the edge and maintain a connection pool to prevent us having to make a new database connection on every request. You will learn how to: Build and deploy a Cloudflare Worker. Use Worker secrets with the Wrangler CLI. Deploy a Timescale database service. Connect your Worker to your Timescale database service with Hyperdrive. Query your new API. You can learn more about Timescale by reading their documentation. 1. Create a Worker project Run the following command to create a Worker project from the command line: Make note of the URL that your application was deployed to. You will be using it when you configure your GitHub webhook. Change into the directory you just created for your Worker project: cd timescale-api 2. Prepare your Timescale Service :::note If you have not signed up for Timescale, go to the signup page where you can start a free 30 day trial with no credit card. ::: If you are creating a new service, go to the Timescale Console and follow these steps: Select Create Service by selecting the black plus in the upper right. Choose Time Series as the service type. Choose your desired region and instance size. 1 CPU will be enough for this tutorial. Set a service name to replace the randomly generated one. Select Create Service. On the right hand side, expand the Connection Info dialog and copy the Service URL. Copy the password which is displayed. You will not be able to retrieve this again. Select I stored my password, go to service overview. If you are using a service you created previously, you can retrieve your service connection information in the Timescale Console: Select the service (database) you want Hyperdrive to connect to. Expand Connection info. Copy the Service URL. The Service URL is the connection string that Hyperdrive will use to connect. This string includes the database hostname, port number and database name. :::note If you do not have your password stored, you will need to select Forgot your password? and set a new SCRAM password. Save this password, as Timescale will only display it once. You should ensure that you do not break any existing clients if when you reset the password. ::: Insert your password into the Service URL as follows (leaving the portion after the @ untouched): postgres://tsdbadmin:YOURPASSWORD@... This will be referred to as SERVICEURL in the following sections. 3. Create your Hypertable Timescale allows you to convert regular PostgreSQL tables into hypertables, tables used to deal with time-series, events, or analytics data. Once you have made this change, Timescale will seamlessly manage the hypertable's partitioning, as well as allow you to apply other features like compression or continuous aggregates. Connect to your Timescale database using the Service URL you copied in the last step (it has the password embedded). If you are using the default PostgreSQL CLI tool psql to connect, you would run psql like below (substituting your Service URL from the previous step). You could also connect using a graphical tool like PgAdmin. psql Once you are connected, create your table by pasting the following SQL: CREATE TABLE readings( ts timestamptz DEFAULT now() NOT NULL, sensor UUID NOT NULL, metadata jsonb, value numeric NOT NULL ); SELECT create_hypertable('readings', 'ts'); Timescale will manage the rest for you as you ingest and query data. 4. Create a database configuration To create a new Hyperdrive instance you will need: Your SERVICEURL from step 2. A name for your Hyperdrive service. For this tutorial, you will use hyperdrive. Hyperdrive uses the create command with the --connection-string argument to pass this information. Run it as follows: npx wrangler hyperdrive create hyperdrive --connection-string="SERVICEURL" :::note Hyperdrive will attempt to connect to your database with the provided credentials to verify they are correct before creating a configuration. If you encounter an error when attempting to connect, refer to Hyperdrive's troubleshooting documentation to debug possible causes. ::: This command outputs your Hyperdrive ID. You can now bind your Hyperdrive configuration to your Worker in your Wrangler configuration by replacing the content with the following: { "$schema": "./node_modules/wrangler/config-schema.json", "name": "timescale-api", "main": "src/index.ts", "upload_source_maps": true, "compatibility_date": "$today", "compatibility_flags": [ "nodejs_compat" ], "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "your-id-here" } ] } Install the Postgres driver into your Worker project: Now copy the below Worker code, and replace the current code in ./src/index.ts. The code below: Uses Hyperdrive to connect to Timescale using the connection string generated from env.HYPERDRIVE.connectionString directly to the driver. Creates a POST route which accepts an array of JSON readings to insert into Timescale in one transaction. Creates a GET route which takes a limit parameter and returns the most recent readings. This could be adapted to filter by ID or by timestamp. import { Client } from "pg"; export interface Env { HYPERDRIVE: Hyperdrive; } export default { async fetch(request, env, ctx): Promise { // Create a new client on each request. Hyperdrive maintains the underlying // database connection pool, so creating a new client is fast. const client = new Client({ connectionString: env.HYPERDRIVE.connectionString, }); await client.connect(); const url = new URL(request.url); // Create a route for inserting JSON as readings if (request.method === "POST" && url.pathname === "/readings") { // Parse the request's JSON payload const productData = await request.json(); // Write the raw query. You are using jsonb_to_recordset to expand the JSON // to PG INSERT format to insert all items at once, and using coalesce to // insert with the current timestamp if no ts field exists const insertQuery = ` INSERT INTO readings (ts, sensor, metadata, value) SELECT coalesce(ts, now()), sensor, metadata, value FROM jsonb_to_recordset($1::jsonb) AS t(ts timestamptz, sensor UUID, metadata jsonb, value numeric) `; const insertResult = await client.query(insertQuery, [ JSON.stringify(productData), ]); // Collect the raw row count inserted to return const resp = new Response(JSON.stringify(insertResult.rowCount), { headers: { "Content-Type": "application/json" }, }); return resp; // Create a route for querying within a time-frame } else if (request.method === "GET" && url.pathname === "/readings") { const limit = url.searchParams.get("limit"); // Query the readings table using the limit param passed const result = await client.query( "SELECT * FROM readings ORDER BY ts DESC LIMIT $1", [limit], ); // Return the result as JSON const resp = new Response(JSON.stringify(result.rows), { headers: { "Content-Type": "application/json" }, }); return resp; } }, } satisfies ExportedHandler; 5. Deploy your Worker Run the following command to redeploy your Worker: npx wrangler deploy Your application is now live and accessible at timescale-api..workers.dev. The exact URI will be shown in the output of the wrangler command you just ran. After deploying, you can interact with your Timescale IoT readings database using your Cloudflare Worker. Connection from the edge will be faster because you are using Cloudflare Hyperdrive to connect from the edge. You can now use your Cloudflare Worker to insert new rows into the readings table. To test this functionality, send a POST request to your Worker’s URL with the /readings path, along with a JSON payload containing the new product data: [ { "sensor": "6f3e43a4-d1c1-4cb6-b928-0ac0efaf84a5", "value": 0.3 }, { "sensor": "d538f9fa-f6de-46e5-9fa2-d7ee9a0f0a68", "value": 10.8 }, { "sensor": "5cb674a0-460d-4c80-8113-28927f658f5f", "value": 18.8 }, { "sensor": "03307bae-d5b8-42ad-8f17-1c810e0fbe63", "value": 20.0 }, { "sensor": "64494acc-4aa5-413c-bd09-2e5b3ece8ad7", "value": 13.1 }, { "sensor": "0a361f03-d7ec-4e61-822f-2857b52b74b3", "value": 1.1 }, { "sensor": "50f91cdc-fd19-40d2-b2b0-c90db3394981", "value": 10.3 } ] This tutorial omits the ts (the timestamp) and metadata (the JSON blob) so they will be set to now() and NULL respectively. Once you have sent the POST request you can also issue a GET request to your Worker’s URL with the /readings path. Set the limit parameter to control the amount of returned records. If you have curl installed you can test with the following commands (replace with your subdomain from the deploy command above): curl --request POST --data @- 'https://timescale-api..workers.dev/readings' <.workers.dev/readings?limit=10" In this tutorial, you have learned how to create a working example to ingest and query readings from the edge with Timescale, Workers, Hyperdrive, and TypeScript. Next steps Learn more about How Hyperdrive Works. Learn more about Timescale. Refer to the troubleshooting guide to debug common issues.