cloudflare-hyperdrive by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill cloudflare-hyperdrive状态 : 生产就绪 ✅ 最后更新 : 2026-01-09 依赖项 : cloudflare-worker-base(Worker 设置推荐) 最新版本 : wrangler@4.58.0, pg@8.16.3+(最低要求), postgres@3.4.8, mysql2@3.16.0
近期更新 (2025) :
# For PostgreSQL
npx wrangler hyperdrive create my-postgres-db \
--connection-string="postgres://user:password@db-host.cloud:5432/database"
# For MySQL
npx wrangler hyperdrive create my-mysql-db \
--connection-string="mysql://user:password@db-host.cloud:3306/database"
# Output:
# ✅ Successfully created Hyperdrive configuration
#
# [[hyperdrive]]
# binding = "HYPERDRIVE"
# id = "a76a99bc-7901-48c9-9c15-c4b11b559606"
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
保存 id 值 - 下一步会用到它!
添加到你的 wrangler.jsonc:
{
"name": "my-worker",
"main": "src/index.ts",
"compatibility_date": "2024-09-23",
"compatibility_flags": ["nodejs_compat"], // 数据库驱动必需
"hyperdrive": [
{
"binding": "HYPERDRIVE", // 在代码中作为 env.HYPERDRIVE 访问
"id": "a76a99bc-7901-48c9-9c15-c4b11b559606" // 来自 wrangler hyperdrive create
}
]
}
关键点:
nodejs_compat 标志是所有数据库驱动必需的binding 是你在代码中访问 Hyperdrive 的方式 (env.HYPERDRIVE)id 是 Hyperdrive 配置 ID(不是你的数据库 ID)# For PostgreSQL (choose one)
npm install pg # node-postgres (最常用)
npm install postgres # postgres.js (现代,最低 v3.4.5)
# For MySQL
npm install mysql2 # mysql2 (最低 v3.13.0)
PostgreSQL 使用 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 使用 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 // Workers 必需 (eval() 不支持)
});
try {
const [rows] = await connection.query('SELECT * FROM users LIMIT 10');
return Response.json({ users: rows });
} finally {
ctx.waitUntil(connection.end());
}
}
};
npx wrangler deploy
完成! 你的 Worker 现在通过 Hyperdrive 连接到你的现有数据库,具备:
此技能预防了 11 个有记录的问题及其解决方案。
错误 : 连接失败,主机名类似 xxx.hyperdrive.local 来源 : GitHub Issue #11556 平台 : Windows, macOS 26 Tahoe, Ubuntu 24.04 LTS (wrangler@4.54.0+) 原因 : Hyperdrive 本地代理主机名在某些平台上无法解析 预防 :
本地开发使用环境变量:
export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@localhost:5432/db"
npx wrangler dev
或使用 wrangler dev --remote(注意:使用生产数据库)
状态 : 问题未解决,有变通方案
错误 : 连接无限期挂起,无错误信息 来源 : GitHub Issue #6179 原因 : 在连接字符串中使用 IP 地址而非主机名导致 postgres.js 挂起 预防 :
// ❌ 错误 - IP 地址导致无限期挂起
const connection = "postgres://user:password@192.168.1.100:5432/db"
// ✅ 正确 - 使用主机名
const connection = "postgres://user:password@db.example.com:5432/db"
额外陷阱 : Miniflare(本地开发)仅支持密码中的 A-z0-9 字符,尽管 Postgres 允许特殊字符。本地开发请使用简单密码。
错误 : "不支持的身份验证方法" 来源 : GitHub Issue #10617 原因 : MySQL 8.0.43+ 引入了 Hyperdrive 不支持的新身份验证方法 预防 :
使用 MySQL 8.0.40 或更早版本,或配置用户使用受支持的身份验证插件:
ALTER USER 'username'@'%' IDENTIFIED WITH caching_sha2_password BY 'password';
受支持的身份验证插件 : 仅 caching_sha2_password 和 mysql_native_password 状态 : 已知问题,跟踪为 CFSQL-1392
错误 : 需要 SSL 但在本地开发中连接失败 来源 : GitHub Issue #10124 原因 : Hyperdrive 本地模式不支持到远程数据库(例如 Neon、云提供商)的 SSL 连接 预防 :
在代码中使用条件连接:
const url = env.isLocal ? env.DB_URL : env.HYPERDRIVE.connectionString;
const client = postgres(url, {
fetch_types: false,
max: 2,
});
替代方案 : 使用 wrangler dev --remote(⚠️ 连接到生产数据库) 时间线 : SSL 支持计划于 2026 年(需要 workerd/Workers 运行时更改,跟踪为 SQC-645)
错误 : SET 语句在查询之间不持久 来源 : Cloudflare Hyperdrive 文档 - Hyperdrive 工作原理 原因 : Hyperdrive 在事务模式下运行,连接在每个事务和 RESET 后返回到池中 预防 :
// ❌ 错误 - SET 不会在查询之间持久
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable'); // 使用默认的 search_path!
// ✅ 正确 - 在事务内 SET
await client.query('BEGIN');
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable'); // 现在使用 myschema
await client.query('COMMIT');
⚠️ 警告 : 将多个操作包装在单个事务中以维持 SET 状态会影响 Hyperdrive 的性能和扩展性。
错误 : Worker 在第一个请求后挂起并超时 来源 : GitHub Issue #28193 已验证 : 多位用户确认 原因 : Prisma 的连接池尝试跨请求上下文重用连接,违反了 Workers 的 I/O 隔离 预防 :
// ❌ 错误 - 全局 Prisma client 跨请求重用
const prisma = new PrismaClient({ adapter });
export default {
async fetch(request: Request, env: Bindings) {
// 第一个请求: 工作
// 后续请求: 无限期挂起
const users = await prisma.user.findMany();
return Response.json({ users });
}
};
// ✅ 正确 - 每个请求创建新的 client
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const pool = new Pool({
connectionString: env.HYPERDRIVE.connectionString,
max: 5
});
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });
try {
const users = await prisma.user.findMany();
return Response.json({ users });
} finally {
ctx.waitUntil(pool.end());
}
}
};
错误 : 使用 Neon serverless driver 时 Hyperdrive 没有益处 来源 : Neon GitHub 仓库, Cloudflare 文档 原因 : Neon 的 serverless driver 使用 WebSockets 而非 TCP,绕过了 Hyperdrive 的连接池 预防 :
// ❌ 错误 - Neon serverless driver 绕过 Hyperdrive
import { neon } from '@neondatabase/serverless';
const sql = neon(env.HYPERDRIVE.connectionString);
// 这使用 WebSockets,不是 TCP - Hyperdrive 没有帮助
// ✅ 正确 - 使用传统的 TCP driver 配合 Hyperdrive
import postgres from 'postgres';
const sql = postgres(env.HYPERDRIVE.connectionString, {
prepare: true,
max: 5
});
官方建议 : Neon 文档指出"在 Cloudflare Workers 上,考虑使用 Cloudflare Hyperdrive 而不是此驱动"
错误 : 双重池化导致连接问题 来源 : Cloudflare 文档 - Supabase 原因 : 使用 Supabase 池化连接 (Supavisor) 会造成双重池化;Supavisor 不支持预处理语句 预防 :
# ❌ 错误 - 使用 Supabase 池化连接 (Supavisor)
npx wrangler hyperdrive create my-supabase \
--connection-string="postgres://user:password@aws-0-us-west-1.pooler.supabase.com:6543/postgres"
# ✅ 正确 - 使用 Supabase 直接连接
npx wrangler hyperdrive create my-supabase \
--connection-string="postgres://user:password@db.projectref.supabase.co:5432/postgres"
原因 : Hyperdrive 提供自己的池化;双重池化会导致问题并破坏缓存
错误 : 大约 95% 的时间出现 500 错误 来源 : GitHub Issue #3893 已验证 : 多位用户复现 原因 : Nitro 3 内置的 useDatabase (db0/integrations/drizzle) 存在 I/O 隔离问题 预防 :
// ❌ 错误 - Nitro 的 useDatabase 约 95% 的时间失败
import { useDatabase } from 'db0';
import { drizzle } from 'db0/integrations/drizzle';
export default eventHandler(async () => {
const db = useDatabase();
const users = await drizzle(db).select().from(usersTable);
// 约 95% 的时间失败并出现 500 错误
});
// ✅ 正确 - 直接创建 Drizzle client
import postgres from 'postgres';
import { drizzle } from 'drizzle-orm/postgres-js';
export default eventHandler(async (event) => {
const sql = postgres(event.context.cloudflare.env.HYPERDRIVE.connectionString, {
max: 5,
prepare: true
});
const db = drizzle(sql);
const users = await db.select().from(usersTable);
event.context.cloudflare.ctx.waitUntil(sql.end());
return { users };
});
错误信息 : "无法代表另一个请求执行 I/O"
错误 : 预处理语句缓存无法正常工作 来源 : Cloudflare 文档 原因 : postgres.js 3.4.5 之前的版本不支持 Hyperdrive 的预处理语句缓存 预防 :
# Hyperdrive 兼容性的最低版本
npm install postgres@3.4.5
# 当前推荐版本
npm install postgres@3.4.8
相关 : 2025年5月的预处理语句缓存改进要求最低版本 3.4.5
错误 : Hyperdrive 没有益处或导致连接问题 来源 : 来自 Neon serverless driver 问题的一般模式 原因 : Hyperdrive 需要 TCP 连接;基于 WebSocket 的驱动绕过了 TCP 池化层 预防 :
使用传统的基于 TCP 的驱动(pg, postgres.js, mysql2)而非基于 WebSocket 的驱动。
受影响的驱动 : 任何使用 WebSockets 而非 TCP 的数据库驱动
Hyperdrive 通过以下方式消除了 7 次连接往返(TCP + TLS + 身份验证):
结果 : 单区域数据库感觉像全局分布。
# PostgreSQL
postgres://user:password@host:5432/database
postgres://user:password@host:5432/database?sslmode=require
# MySQL
mysql://user:password@host:3306/database
# URL 编码特殊字符: p@ssw$rd → p%40ssw%24rd
const client = new Client({ connectionString: env.HYPERDRIVE.connectionString });
await client.connect();
const result = await client.query('SELECT ...');
ctx.waitUntil(client.end()); // 关键: 非阻塞清理
适用于 : 简单查询,每个请求单个查询
const pool = new Pool({
connectionString: env.HYPERDRIVE.connectionString,
max: 5 // 关键: Workers 限制为 6 个连接 (2025年7月: 可配置约20个免费版,~100个付费版)
});
const [result1, result2] = await Promise.all([
pool.query('SELECT ...'),
pool.query('SELECT ...')
]);
ctx.waitUntil(pool.end());
适用于 : 单个请求中的并行查询
始终使用 ctx.waitUntil(client.end()) - 响应发送后非阻塞清理 切勿使用 await client.end() - 阻塞响应,增加延迟
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
const sql = postgres(env.HYPERDRIVE.connectionString, { max: 5 });
const db = drizzle(sql);
const allUsers = await db.select().from(users);
ctx.waitUntil(sql.end());
⚠️ 关键 : 在 Workers 中不要跨请求重用 Prisma client。每个请求创建新的 client。
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "@prisma/client";
import { Pool } from "pg";
// ❌ 错误 - 全局 client 导致第一个请求后挂起
const prisma = new PrismaClient({ adapter });
export default {
async fetch(request: Request, env: Bindings) {
const users = await prisma.user.findMany(); // 第一个请求后挂起
return Response.json({ users });
}
};
// ✅ 正确 - 每个请求的 client
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const pool = new Pool({ connectionString: env.HYPERDRIVE.connectionString, max: 5 });
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });
try {
const users = await prisma.user.findMany();
return Response.json({ users });
} finally {
ctx.waitUntil(pool.end());
}
}
};
原因 : Prisma 的连接池尝试跨请求上下文重用连接,违反了 Workers 的 I/O 隔离。来源: GitHub Issue #28193
注意 : Prisma 需要驱动适配器 (@prisma/adapter-pg)。
重要 : 本地 Hyperdrive 连接不支持 SSL。这会影响需要 SSL 的数据库(例如 Neon、大多数云提供商)。
变通方案 - 条件连接 :
const url = env.isLocal ? env.DB_URL : env.HYPERDRIVE.connectionString;
const client = postgres(url, {
fetch_types: false,
max: 2,
});
替代方案 : 使用 wrangler dev --remote(⚠️ 连接到生产数据库)
时间线 : SSL 支持计划于 2026 年(需要 workerd/Workers 运行时更改) 来源 : GitHub Issue #10124, 跟踪为 SQC-645
选项 1: 环境变量(推荐)
export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@localhost:5432/local_db"
npx wrangler dev
配置可安全提交,wrangler.jsonc 中无凭据。
选项 2: wrangler.jsonc 中的 localConnectionString
{ "hyperdrive": [{ "binding": "HYPERDRIVE", "id": "prod-id", "localConnectionString": "postgres://..." }] }
⚠️ 不要将凭据提交到版本控制。
选项 3: 远程开发
npx wrangler dev --remote # ⚠️ 使用生产数据库
缓存 : SELECT(非变更查询) 不缓存 : INSERT, UPDATE, DELETE, 易变函数 (LASTVAL, LAST_INSERT_ID)
2025年5月 : 通过区域化预处理语句缓存,缓存命中速度提升 5 倍。
postgres.js 关键点:
const sql = postgres(env.HYPERDRIVE.connectionString, {
prepare: true // 缓存必需
});
检查缓存状态:
response.headers.get('cf-cache-status'); // HIT, MISS, BYPASS, EXPIRED
SSL 模式 : require(默认), verify-ca(验证 CA), verify-full(验证 CA + 主机名)
服务器证书 (verify-ca/verify-full):
npx wrangler cert upload certificate-authority --ca-cert root-ca.pem --name my-ca-cert
npx wrangler hyperdrive create my-db --connection-string="postgres://..." --ca-certificate-id <ID> --sslmode verify-full
客户端证书 (mTLS):
npx wrangler cert upload mtls-certificate --cert client-cert.pem --key client-key.pem --name my-cert
npx wrangler hyperdrive create my-db --connection-string="postgres://..." --mtls-certificate-id <ID>
连接到私有网络(VPC、本地部署)中的数据库:
# 1. 安装 cloudflared (macOS: brew install cloudflare/cloudflare/cloudflared)
# 2. 创建隧道
cloudflared tunnel create my-db-tunnel
# 3. 配置 config.yml
# tunnel: <TUNNEL_ID>
# ingress:
# - hostname: db.example.com
# service: tcp://localhost:5432
# 4. 运行隧道
cloudflared tunnel run my-db-tunnel
# 5. 创建 Hyperdrive
npx wrangler hyperdrive create my-private-db --connection-string="postgres://user:password@db.example.com:5432/database"
✅ 在 compatibility_flags 中包含 nodejs_compat ✅ 使用 ctx.waitUntil(client.end()) 进行连接清理 ✅ 为连接池设置 max: 5(Workers 限制:6) ✅ 在你的数据库上启用 TLS/SSL(Hyperdrive 需要它) ✅ 为缓存启用预处理语句(postgres.js: prepare: true) ✅ 为 mysql2 驱动设置 disableEval: true ✅ 使用 try/catch 优雅地处理错误 ✅ 使用环境变量作为本地开发连接字符串 ✅ 部署前使用 wrangler dev 进行本地测试
❌ 跳过 nodejs_compat 标志(导致"没有此模块"错误) ❌ 直接使用私有 IP 地址(改用 Cloudflare Tunnel) ❌ 使用 await client.end()(阻塞响应,使用 ctx.waitUntil()) ❌ 设置连接池 max > 5(超过 Workers 的 6 连接限制) ❌ 将所有查询包装在事务中(限制连接多路复用) ❌ 使用 SQL 级别的 PREPARE/EXECUTE/DEALLOCATE(不支持) ❌ 使用咨询锁、LISTEN/NOTIFY(PostgreSQL 不支持的功能) ❌ 在 MySQL 中使用多语句查询(不支持) ❌ 将数据库凭据提交到版本控制 ❌ 在连接字符串中使用 IP 地址而非主机名(导致 postgres.js 挂起) ❌ 将 Neon serverless driver 与 Hyperdrive 一起使用(使用 WebSockets,绕过池化) ❌ 将 Supabase 池化连接字符串 (Supavisor) 与 Hyperdrive 一起使用(双重池化) ❌ 在 Workers 中跨请求重用 Prisma client 实例(导致挂起和超时) ❌ 将 Nitro 3 的 useDatabase 与 Drizzle 和 Hyperdrive 一起使用(约 95% 失败率) ❌ 期望 SET 语句在查询之间持久(事务模式重置连接) ❌ 使用 3.4.5 之前的 postgres.js 版本(破坏预处理语句缓存)
# Create Hyperdrive configuration
wrangler hyperdrive create <name> --connection-string="postgres://..."
# List all Hyperdrive configurations
wrangler hyperdrive list
# Get details of a configuration
wrangler hyperdrive get <hyperdrive-id>
# Update connection string
wrangler hyperdrive update <hyperdrive-id> --connection-string="postgres://..."
# Delete configuration
wrangler hyperdrive delete <hyperdrive-id>
# Upload CA certificate
wrangler cert upload certificate-authority --ca-cert <file>.pem --name <name>
# Upload client certificate pair
wrangler cert upload mtls-certificate --cert <cert>.pem --key <key>.pem --name <name>
PostgreSQL (v9.0-17.x) : AWS RDS/Aurora, Google Cloud SQL, Azure, Neon, Supabase, PlanetScale, Timescale, CockroachDB, Materialize, Fly.io, pgEdge, Prisma Postgres
MySQL (v5.7-8.x) : AWS RDS/Aurora, Google Cloud SQL, Azure, PlanetScale, MariaDB (2025年4月 正式版)
不支持 : SQL Server, MongoDB, Oracle
PREPARE, EXECUTE, DEALLOCATE)LISTEN 和 NOTIFYUSE 语句COM_STMT_PREPARE)COM_INIT_DB 消息caching_sha2_password 或 mysql_native_password 之外的身份验证插件变通方案 : 对于不支持的功能,创建第二个直接客户端连接(不使用 Hyperdrive)。
prepare: true)完整的错误参考及解决方案,请参阅 references/troubleshooting.md。
快速修复:
| 错误 | 解决方案 |
|---|---|
| "没有此模块 'node:*'" | 将 nodejs_compat 添加到 compatibility_flags |
| "数据库不支持 TLS" | 在你的数据库上启用 SSL/TLS |
| "连接被拒绝" | 检查防火墙规则,允许公共互联网或使用 Tunnel |
| "获取连接失败" | 使用 ctx.waitUntil() 进行清理,避免长时间事务 |
| "不允许从字符串生成代码" | 在 mysql2 配置中设置 disableEval: true |
| "错误的主机名" | 验证 DNS 解析,检查拼写错误 |
| "无效的数据库凭据" | 检查用户名/密码(区分大小写) |
Hyperdrive 仪表板 → 选择配置 → 指标标签页
可用 : 查询计数、缓存命中率、查询延迟 (p50/p95/p99)、连接延迟、查询/结果字节数、错误率
# Option 1: Create new config (zero downtime)
wrangler hyperdrive create my-db-v2 --connection-string="postgres://new-creds..."
# Update wrangler.jsonc, deploy, delete old config
# Option 2: Update existing
wrangler hyperdrive update <id> --connection-string="postgres://new-creds..."
最佳实践 : 为暂存/生产环境使用单独的配置。
最后验证 : 2026-01-21 | 技能版本 : 3.0.0 | 变更 : 添加了 11 个已知问题预防条目(6 个 TIER 1,5 个 TIER 2),扩展了 Prisma/本地开发/性能部分并添加了关键警告,更新了"切勿做"规则
包版本 : wrangler@4.58.0, pg@8.16.3+(最低要求), postgres@3.4.5+(缓存最低要求), postgres@3.4.8(推荐), mysql2@3.16.0 生产环境测试 : 基于官方 Cloudflare 文档和社区示例
每周安装
323
仓库
GitHub Stars
643
首次出现
Jan 20, 2026
安全审计
安装于
claude-code268
gemini-cli218
opencode216
cursor202
antigravity196
codex189
Status : Production Ready ✅ Last Updated : 2026-01-09 Dependencies : cloudflare-worker-base (recommended for Worker setup) Latest Versions : wrangler@4.58.0, pg@8.16.3+ (minimum), postgres@3.4.8, mysql2@3.16.0
Recent Updates (2025) :
# For PostgreSQL
npx wrangler hyperdrive create my-postgres-db \
--connection-string="postgres://user:password@db-host.cloud:5432/database"
# For MySQL
npx wrangler hyperdrive create my-mysql-db \
--connection-string="mysql://user:password@db-host.cloud:3306/database"
# Output:
# ✅ Successfully created Hyperdrive configuration
#
# [[hyperdrive]]
# binding = "HYPERDRIVE"
# id = "a76a99bc-7901-48c9-9c15-c4b11b559606"
Save theid value - you'll need it in the next step!
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 driversbinding is how you access Hyperdrive in code (env.HYPERDRIVE)id is the Hyperdrive configuration ID (NOT your database ID)# For PostgreSQL (choose one)
npm install pg # node-postgres (most common)
npm install postgres # postgres.js (modern, minimum v3.4.5)
# For MySQL
npm install mysql2 # mysql2 (minimum v3.13.0)
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 {
// Clean up connection AFTER response is sent
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 // REQUIRED for Workers (eval() not supported)
});
try {
const [rows] = await connection.query('SELECT * FROM users LIMIT 10');
return Response.json({ users: rows });
} finally {
ctx.waitUntil(connection.end());
}
}
};
npx wrangler deploy
That's it! Your Worker now connects to your existing database via Hyperdrive with:
This skill prevents 11 documented issues with sources and solutions.
Error : Connection fails with hostname like xxx.hyperdrive.local Source : GitHub Issue #11556 Platforms : Windows, macOS 26 Tahoe, Ubuntu 24.04 LTS (wrangler@4.54.0+) 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
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 :
// ❌ WRONG - IP address causes indefinite hang
const connection = "postgres://user:password@192.168.1.100:5432/db"
// ✅ CORRECT - Use hostname
const connection = "postgres://user:password@db.example.com: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.
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
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)
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 :
// ❌ WRONG - SET won't persist across queries
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable'); // Uses default search_path!
// ✅ CORRECT - SET within transaction
await client.query('BEGIN');
await client.query('SET search_path TO myschema');
await client.query('SELECT * FROM mytable'); // Now uses myschema
await client.query('COMMIT');
⚠️ WARNING : Wrapping multiple operations in a single transaction to maintain SET state will affect Hyperdrive's performance and scaling.
Error : Worker hangs and times out after first request Source : GitHub Issue #28193 Verified : Multiple users confirmed Why It Happens : Prisma's connection pool attempts to reuse connections across request contexts, violating Workers' I/O isolation Prevention :
// ❌ WRONG - Global Prisma client reused across requests
const prisma = new PrismaClient({ adapter });
export default {
async fetch(request: Request, env: Bindings) {
// First request: works
// Subsequent requests: hang indefinitely
const users = await prisma.user.findMany();
return Response.json({ users });
}
};
// ✅ CORRECT - Create new client per request
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const pool = new Pool({
connectionString: env.HYPERDRIVE.connectionString,
max: 5
});
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });
try {
const users = await prisma.user.findMany();
return Response.json({ users });
} finally {
ctx.waitUntil(pool.end());
}
}
};
Error : Hyperdrive provides no benefit with Neon serverless driver Source : Neon GitHub Repo, Cloudflare Docs Why It Happens : Neon's serverless driver uses WebSockets instead of TCP, bypassing Hyperdrive's connection pooling Prevention :
// ❌ WRONG - Neon serverless driver bypasses Hyperdrive
import { neon } from '@neondatabase/serverless';
const sql = neon(env.HYPERDRIVE.connectionString);
// This uses WebSockets, not TCP - Hyperdrive doesn't help
// ✅ CORRECT - Use traditional TCP driver with Hyperdrive
import postgres from 'postgres';
const sql = postgres(env.HYPERDRIVE.connectionString, {
prepare: true,
max: 5
});
Official Recommendation : Neon documentation states "On Cloudflare Workers, consider using Cloudflare Hyperdrive instead of this driver"
Error : Double-pooling causes connection issues Source : Cloudflare Docs - Supabase Why It Happens : Using Supabase pooled connection (Supavisor) creates double-pooling; Supavisor doesn't support prepared statements Prevention :
# ❌ WRONG - Using Supabase pooled connection (Supavisor)
npx wrangler hyperdrive create my-supabase \
--connection-string="postgres://user:password@aws-0-us-west-1.pooler.supabase.com:6543/postgres"
# ✅ CORRECT - Use Supabase direct connection
npx wrangler hyperdrive create my-supabase \
--connection-string="postgres://user:password@db.projectref.supabase.co:5432/postgres"
Reason : Hyperdrive provides its own pooling; double-pooling causes issues and breaks caching
Error : 500 errors approximately 95% of the time Source : GitHub Issue #3893 Verified : Reproduced by multiple users Why It Happens : Nitro 3's built-in useDatabase (db0/integrations/drizzle) has I/O isolation issues Prevention :
// ❌ WRONG - Nitro's useDatabase fails ~95% of the time
import { useDatabase } from 'db0';
import { drizzle } from 'db0/integrations/drizzle';
export default eventHandler(async () => {
const db = useDatabase();
const users = await drizzle(db).select().from(usersTable);
// Fails ~95% of the time with 500 error
});
// ✅ CORRECT - Create Drizzle client directly
import postgres from 'postgres';
import { drizzle } from 'drizzle-orm/postgres-js';
export default eventHandler(async (event) => {
const sql = postgres(event.context.cloudflare.env.HYPERDRIVE.connectionString, {
max: 5,
prepare: true
});
const db = drizzle(sql);
const users = await db.select().from(usersTable);
event.context.cloudflare.ctx.waitUntil(sql.end());
return { users };
});
Error Message : "Cannot perform I/O on behalf of a different request"
Error : Prepared statement caching doesn't work properly Source : Cloudflare Docs Why It Happens : postgres.js versions before 3.4.5 don't support Hyperdrive's prepared statement caching properly Prevention :
# Minimum version for Hyperdrive compatibility
npm install postgres@3.4.5
# Current recommended version
npm install postgres@3.4.8
Related : May 2025 prepared statement caching improvements require minimum version 3.4.5
Error : Hyperdrive provides no benefit or causes connection issues Source : General pattern from Neon serverless driver issue Why It Happens : Hyperdrive requires TCP connections; WebSocket-based drivers bypass the TCP pooling layer Prevention :
Use traditional TCP-based drivers (pg, postgres.js, mysql2) instead of WebSocket-based drivers.
Affected Drivers : Any database driver using WebSockets instead of TCP
Hyperdrive eliminates 7 connection round trips (TCP + TLS + auth) by:
Result : Single-region databases feel globally distributed.
# PostgreSQL
postgres://user:password@host:5432/database
postgres://user:password@host:5432/database?sslmode=require
# MySQL
mysql://user:password@host:3306/database
# URL-encode special chars: p@ssw$rd → p%40ssw%24rd
const client = new Client({ connectionString: env.HYPERDRIVE.connectionString });
await client.connect();
const result = await client.query('SELECT ...');
ctx.waitUntil(client.end()); // CRITICAL: Non-blocking cleanup
Use for : Simple queries, single query per request
const pool = new Pool({
connectionString: env.HYPERDRIVE.connectionString,
max: 5 // CRITICAL: Workers limit is 6 connections (July 2025: configurable ~20 Free, ~100 Paid)
});
const [result1, result2] = await Promise.all([
pool.query('SELECT ...'),
pool.query('SELECT ...')
]);
ctx.waitUntil(pool.end());
Use for : Parallel queries in single request
ALWAYS usectx.waitUntil(client.end()) - non-blocking cleanup after response sent NEVER useawait client.end() - blocks response, adds latency
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
const sql = postgres(env.HYPERDRIVE.connectionString, { max: 5 });
const db = drizzle(sql);
const allUsers = await db.select().from(users);
ctx.waitUntil(sql.end());
⚠️ CRITICAL : Do NOT reuse Prisma client across requests in Workers. Create new client per request.
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "@prisma/client";
import { Pool } from "pg";
// ❌ WRONG - Global client causes hangs after first request
const prisma = new PrismaClient({ adapter });
export default {
async fetch(request: Request, env: Bindings) {
const users = await prisma.user.findMany(); // Hangs after first request
return Response.json({ users });
}
};
// ✅ CORRECT - Per-request client
export default {
async fetch(request: Request, env: Bindings, ctx: ExecutionContext) {
const pool = new Pool({ connectionString: env.HYPERDRIVE.connectionString, max: 5 });
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });
try {
const users = await prisma.user.findMany();
return Response.json({ users });
} finally {
ctx.waitUntil(pool.end());
}
}
};
Why : Prisma's connection pool attempts to reuse connections across request contexts, violating Workers' I/O isolation. Source: GitHub Issue #28193
Note : Prisma requires driver adapters (@prisma/adapter-pg).
Important : Local Hyperdrive connections do NOT support SSL. This affects databases that require SSL (e.g., Neon, most cloud providers).
Workaround - Conditional Connection :
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) Source : GitHub Issue #10124, tracked as SQC-645
Option 1: Environment Variable (Recommended)
export CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE="postgres://user:password@localhost:5432/local_db"
npx wrangler dev
Safe to commit config, no credentials in wrangler.jsonc.
Option 2: localConnectionString in wrangler.jsonc
{ "hyperdrive": [{ "binding": "HYPERDRIVE", "id": "prod-id", "localConnectionString": "postgres://..." }] }
⚠️ Don't commit credentials to version control.
Option 3: Remote Development
npx wrangler dev --remote # ⚠️ Uses PRODUCTION database
Cached : SELECT (non-mutating queries) NOT Cached : INSERT, UPDATE, DELETE, volatile functions (LASTVAL, LAST_INSERT_ID)
May 2025 : 5x faster cache hits via regional prepared statement caching.
Critical for postgres.js:
const sql = postgres(env.HYPERDRIVE.connectionString, {
prepare: true // REQUIRED for caching
});
Check cache status:
response.headers.get('cf-cache-status'); // HIT, MISS, BYPASS, EXPIRED
SSL Modes : require (default), verify-ca (verify CA), verify-full (verify CA + hostname)
Server Certificates (verify-ca/verify-full):
npx wrangler cert upload certificate-authority --ca-cert root-ca.pem --name my-ca-cert
npx wrangler hyperdrive create my-db --connection-string="postgres://..." --ca-certificate-id <ID> --sslmode verify-full
Client Certificates (mTLS):
npx wrangler cert upload mtls-certificate --cert client-cert.pem --key client-key.pem --name my-cert
npx wrangler hyperdrive create my-db --connection-string="postgres://..." --mtls-certificate-id <ID>
Connect to databases in private networks (VPCs, on-premises):
# 1. Install cloudflared (macOS: brew install cloudflare/cloudflare/cloudflared)
# 2. Create tunnel
cloudflared tunnel create my-db-tunnel
# 3. Configure config.yml
# tunnel: <TUNNEL_ID>
# ingress:
# - hostname: db.example.com
# service: tcp://localhost:5432
# 4. Run tunnel
cloudflared tunnel run my-db-tunnel
# 5. Create Hyperdrive
npx wrangler hyperdrive create my-private-db --connection-string="postgres://user:password@db.example.com:5432/database"
✅ Include nodejs_compat in compatibility_flags ✅ Use ctx.waitUntil(client.end()) for connection cleanup ✅ Set max: 5 for connection pools (Workers limit: 6) ✅ Enable TLS/SSL on your database (Hyperdrive requires it) ✅ Use prepared statements for caching (postgres.js: prepare: true) ✅ Set disableEval: true for mysql2 driver ✅ Handle errors gracefully with try/catch ✅ Use environment variables for local development connection strings ✅ Test locally with wrangler dev before deploying
❌ Skip nodejs_compat flag (causes "No such module" errors) ❌ Use private IP addresses directly (use Cloudflare Tunnel instead) ❌ Use await client.end() (blocks response, use ctx.waitUntil()) ❌ Set connection pool max > 5 (exceeds Workers' 6 connection limit) ❌ Wrap all queries in transactions (limits connection multiplexing) ❌ Use SQL-level PREPARE/EXECUTE/DEALLOCATE (unsupported) ❌ Use advisory locks, LISTEN/NOTIFY (PostgreSQL unsupported features) ❌ Use multi-statement queries in MySQL (unsupported) ❌ Commit database credentials to version control ❌ Use IP addresses in connection strings instead of hostnames (causes postgres.js to hang) ❌ Use Neon serverless driver with Hyperdrive (uses WebSockets, bypasses pooling) ❌ Use Supabase pooled connection string (Supavisor) with Hyperdrive (double-pooling) ❌ Reuse Prisma client instances across requests in Workers (causes hangs and timeouts) ❌ Use Nitro 3's useDatabase with Drizzle and Hyperdrive (~95% failure rate) ❌ Expect SET statements to persist across queries (transaction mode resets connections) ❌ Use postgres.js versions before 3.4.5 (breaks prepared statement caching)
# Create Hyperdrive configuration
wrangler hyperdrive create <name> --connection-string="postgres://..."
# List all Hyperdrive configurations
wrangler hyperdrive list
# Get details of a configuration
wrangler hyperdrive get <hyperdrive-id>
# Update connection string
wrangler hyperdrive update <hyperdrive-id> --connection-string="postgres://..."
# Delete configuration
wrangler hyperdrive delete <hyperdrive-id>
# Upload CA certificate
wrangler cert upload certificate-authority --ca-cert <file>.pem --name <name>
# Upload client certificate pair
wrangler cert upload mtls-certificate --cert <cert>.pem --key <key>.pem --name <name>
PostgreSQL (v9.0-17.x) : AWS RDS/Aurora, Google Cloud SQL, Azure, Neon, Supabase, PlanetScale, Timescale, CockroachDB, Materialize, Fly.io, pgEdge, Prisma Postgres
MySQL (v5.7-8.x) : AWS RDS/Aurora, Google Cloud SQL, Azure, PlanetScale, MariaDB (April 2025 GA)
NOT Supported : SQL Server, MongoDB, Oracle
PREPARE, EXECUTE, DEALLOCATE)LISTEN and NOTIFYUSE statementsCOM_STMT_PREPARE)COM_INIT_DB messagescaching_sha2_password or mysql_native_passwordWorkaround : For unsupported features, create a second direct client connection (without Hyperdrive).
prepare: true)See references/troubleshooting.md for complete error reference with solutions.
Quick fixes:
| Error | Solution |
|---|---|
| "No such module 'node:*'" | Add nodejs_compat to compatibility_flags |
| "TLS not supported by database" | Enable SSL/TLS on your database |
| "Connection refused" | Check firewall rules, allow public internet or use Tunnel |
| "Failed to acquire connection" | Use ctx.waitUntil() for cleanup, avoid long transactions |
| "Code generation from strings disallowed" | Set disableEval: true in mysql2 config |
| "Bad hostname" | Verify DNS resolves, check for typos |
| "Invalid database credentials" | Check username/password (case-sensitive) |
Hyperdrive Dashboard → Select config → Metrics tab
Available : Query count, cache hit ratio, query latency (p50/p95/p99), connection latency, query/result bytes, error rate
# Option 1: Create new config (zero downtime)
wrangler hyperdrive create my-db-v2 --connection-string="postgres://new-creds..."
# Update wrangler.jsonc, deploy, delete old config
# Option 2: Update existing
wrangler hyperdrive update <id> --connection-string="postgres://new-creds..."
Best practice : Separate configs for staging/production.
Last verified : 2026-01-21 | Skill version : 3.0.0 | Changes : Added 11 Known Issues Prevention entries (6 TIER 1, 5 TIER 2), expanded Prisma/Local Dev/Performance sections with critical warnings, updated Never Do rules
Package Versions : wrangler@4.58.0, pg@8.16.3+ (minimum), postgres@3.4.5+ (minimum for caching), postgres@3.4.8 (recommended), mysql2@3.16.0 Production Tested : Based on official Cloudflare documentation and community examples
Weekly Installs
323
Repository
GitHub Stars
643
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykFail
Installed on
claude-code268
gemini-cli218
opencode216
cursor202
antigravity196
codex189
Supabase Postgres 最佳实践指南 - 8大类别性能优化规则与SQL示例
55,700 周安装