Cloudflare Hyperdrive
Status: Production Ready β
Last Updated: 2026-01-09
Dependencies: cloudflare-worker-base (recommended for Worker setup)
Latest Versions: [email protected], [email protected]+ (minimum), [email protected], [email protected]
Recent Updates (2025):
- July 2025: Configurable connection counts (min 5, max ~20 Free/~100 Paid)
- May 2025: 5x faster cache hits (regional prepared statement caching), FedRAMP Moderate authorization
- April 2025: Free plan availability (10 configs), MySQL GA support
- March 2025: 90% latency reduction (pools near database), IP access control (standard CF IP ranges)
- nodejs_compat_v2: pg driver no longer requires node_compat mode (auto-enabled with compatibility_date 2024-09-23+)
- Limits: 25 Hyperdrive configurations per account (Paid), 10 per account (Free)
Quick Start (5 Minutes)
1. Create Hyperdrive Configuration
npx wrangler hyperdrive create my-postgres-db \
--connection-string="postgres://user:[email protected]:5432/database"
npx wrangler hyperdrive create my-mysql-db \
--connection-string="mysql://user:[email protected]:3306/database"
Save the id value - you'll need it in the next step!
2. Configure Bindings in wrangler.jsonc
Add to your wrangler.jsonc:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2024-09-23",
"compatibility_flags": ["nodejs_compat"], // REQUIRED for database drivers
"hyperdrive": [
{
"binding": "HYPERDRIVE", // Available as env.HYPERDRIVE
"id": "a76a99bc-7901-48c9-9c15-c4b11b559606" // From wrangler hyperdrive create
}
]
}
CRITICAL:
nodejs_compat flag is REQUIRED for all database drivers
binding is how you access Hyperdrive in code (env.HYPERDRIVE)
id is the Hyperdrive configuration ID (NOT your database ID)
3. Install Database Driver
npm install pg
npm install postgres
npm install mysql2
4. Query Your Database
PostgreSQL with node-postgres (pg):
import { Client } from "pg";
type Bindings = {
HYPERDRIVE: Hyperdrive;
};
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const client = new Client({
connectionString: env.HYPERDRIVE.connectionString
});
await client.connect();
try {
const result = await client.query('SELECT * FROM users LIMIT 10');
return Response.json({ users: result.rows });
} finally {
ctx.waitUntil(client.end());
}
}
};
MySQL with mysql2:
import { createConnection } from "mysql2/promise";
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const connection = await createConnection({
host: env.HYPERDRIVE.host,
user: env.HYPERDRIVE.user,
password: env.HYPERDRIVE.password,
database: env.HYPERDRIVE.database,
port: env.HYPERDRIVE.port,
disableEval: true
});
try {
const [rows] = await connection.query('SELECT * FROM users LIMIT 10');
return Response.json({ users: rows });
} finally {
ctx.waitUntil(connection.end());
}
}
};
5. Deploy
npx wrangler deploy
That's it! Your Worker now connects to your existing database via Hyperdrive with:
- β
Global connection pooling
- β
Automatic query caching
- β
Reduced latency (eliminates 7 round trips)
Known Issues Prevention
This skill prevents 11 documented issues with sources and solutions.
Issue #1: Windows/macOS Local Development - Hostname Resolution Failure
Error: Connection fails with hostname like xxx.hyperdrive.local
Source: GitHub Issue #11556
Platforms: Windows, macOS 26 Tahoe, Ubuntu 24.04 LTS ([email protected]+)
Why It Happens: Hyperdrive local proxy hostname fails to resolve on certain platforms
Prevention:
Use environment variable for local development:
export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@localhost:5432/db"
npx wrangler dev
Or use wrangler dev --remote (caution: uses production database)
Status: Open issue, workaround available
Issue #2: postgres.js Hangs with IP Addresses
Error: Connection hangs indefinitely with no error message
Source: GitHub Issue #6179
Why It Happens: Using IP address instead of hostname in connection string causes postgres.js to hang
Prevention:
const connection = "postgres://user:[email protected]:5432/db"
const connection = "postgres://user:[email protected]:5432/db"
Additional Gotcha: Miniflare (local dev) only supports A-z0-9 characters in passwords, despite Postgres allowing special characters. Use simple passwords for local development.
Issue #3: MySQL 8.0.43 Authentication Plugin Not Supported
Error: "unsupported authentication method"
Source: GitHub Issue #10617
Why It Happens: MySQL 8.0.43+ introduces new authentication method not supported by Hyperdrive
Prevention:
Use MySQL 8.0.40 or earlier, or configure user to use supported auth plugin:
ALTER USER 'username'@'%' IDENTIFIED WITH caching_sha2_password BY 'password';
Supported Auth Plugins: Only caching_sha2_password and mysql_native_password
Status: Known issue tracked as CFSQL-1392
Issue #4: Local SSL/TLS Not Supported for Remote Databases
Error: SSL required but connection fails in local development
Source: GitHub Issue #10124
Why It Happens: Hyperdrive local mode doesn't support SSL connections to remote databases (e.g., Neon, cloud providers)
Prevention:
Use conditional connection in code:
const url = env.isLocal ? env.DB_URL : env.HYPERDRIVE.connectionString;
const client = postgres(url, {
fetch_types: false,
max: 2,
});
Alternative: Use wrangler dev --remote (β οΈ connects to production database)
Timeline: SSL support planned for 2026 (requires workerd/Workers runtime changes, tracked as SQC-645)
Issue #5: Transaction Mode Resets SET Statements Between Queries
Error: SET statements don't persist across queries
Source: Cloudflare Hyperdrive Docs - How Hyperdrive Works
Why It Happens: Hyperdrive operates in transaction mode where connections are returned to pool after each transaction and RESET
Prevention:
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable');
await client.query('BEGIN');
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable');
await client.query('COMMIT');
β οΈ WARNING: Wrapping multiple operations in a single transaction to maintain SET state will affect Hyperdrive'