neon-vercel-postgres by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill neon-vercel-postgres状态 : 生产就绪 最后更新 : 2026-01-21 依赖项 : 无 最新版本 : @neondatabase/serverless@1.0.2, @vercel/postgres@0.10.0, drizzle-orm@0.45.1, drizzle-kit@0.31.8, neonctl@2.19.0
选项 A: Neon Direct (多云, Cloudflare Workers, 任何无服务器环境)
npm install @neondatabase/serverless
选项 B: Vercel Postgres (仅限 Vercel, 在 Vercel 上零配置)
npm install @vercel/postgres
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
注意 : 两者使用相同的 Neon 后端。Vercel Postgres 是带有 Vercel 特定环境设置的 Neon。
为何重要:
对于 Neon Direct:
# 在 https://neon.tech 注册
# 创建项目 → 获取连接字符串
# 格式: postgresql://user:password@ep-xyz.region.aws.neon.tech/dbname?sslmode=require
对于 Vercel Postgres:
# 在您的 Vercel 项目中
vercel postgres create
vercel env pull .env.local # 自动创建 POSTGRES_URL 和其他变量
关键:
-pooler.region.aws.neon.tech 结尾)?sslmode=require 参数Neon Direct (Cloudflare Workers, Vercel Edge, Node.js):
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// 简单查询
const users = await sql`SELECT * FROM users WHERE id = ${userId}`;
// 事务
const result = await sql.transaction([
sql`INSERT INTO users (name) VALUES (${name})`,
sql`SELECT * FROM users WHERE name = ${name}`
]);
Vercel Postgres (Next.js Server Actions, API Routes):
import { sql } from '@vercel/postgres';
// 简单查询
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
// 事务
const client = await sql.connect();
try {
await client.sql`BEGIN`;
await client.sql`INSERT INTO users (name) VALUES (${name})`;
await client.sql`COMMIT`;
} finally {
client.release();
}
关键:
sql...``) 以获得自动 SQL 注入防护sql('SELECT * FROM users WHERE id = ' + id) ❌根据您的部署平台选择:
Neon Direct (Cloudflare Workers, 多云, 直接访问 Neon):
npm install @neondatabase/serverless
Vercel Postgres (Vercel 专用, 零配置):
npm install @vercel/postgres
使用 ORM :
# Drizzle ORM (推荐用于边缘兼容性)
npm install drizzle-orm@0.45.1 @neondatabase/serverless@1.0.2
npm install -D drizzle-kit@0.31.8
# Prisma (仅限 Node.js)
npm install prisma @prisma/client @prisma/adapter-neon @neondatabase/serverless
要点:
选项 A: Neon 仪表板
postgresql://user:pass@ep-xyz-pooler.region.aws.neon.tech/db?sslmode=require选项 B: Vercel 仪表板
vercel env pull 以在本地获取环境变量选项 C: Neon CLI (neonctl@2.19.0)
# 安装 CLI
npm install -g neonctl@2.19.0
# 认证
neonctl auth
# 创建项目并获取连接字符串
neonctl projects create --name my-app
neonctl connection-string main
关键:
-pooler.region.aws.neon.tech 结尾)?sslmode=require对于 Neon Direct:
# .env 或 .env.local
DATABASE_URL="postgresql://user:password@ep-xyz-pooler.us-east-1.aws.neon.tech/neondb?sslmode=require"
对于 Vercel Postgres:
# 由 `vercel env pull` 自动创建
POSTGRES_URL="..." # 池化连接(查询时使用此变量)
POSTGRES_PRISMA_URL="..." # 用于 Prisma 迁移
POSTGRES_URL_NON_POOLING="..." # 直接连接(在无服务器环境中避免使用)
POSTGRES_USER="..."
POSTGRES_HOST="..."
POSTGRES_PASSWORD="..."
POSTGRES_DATABASE="..."
对于 Cloudflare Workers (wrangler.jsonc):
{
"vars": {
"DATABASE_URL": "postgresql://user:password@ep-xyz-pooler.us-east-1.aws.neon.tech/neondb?sslmode=require"
}
}
要点:
POSTGRES_URL(池化)POSTGRES_PRISMA_URLPOSTGRES_URL_NON_POOLING选项 A: 原始 SQL
// scripts/migrate.ts
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
await sql`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
)
`;
选项 B: Drizzle ORM (推荐)
// db/schema.ts
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
createdAt: timestamp('created_at').defaultNow()
});
// db/index.ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });
# 运行迁移
npx drizzle-kit generate
npx drizzle-kit migrate
选项 C: Prisma
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("POSTGRES_PRISMA_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now()) @map("created_at")
@@map("users")
}
npx prisma migrate dev --name init
关键:
关键 - 必须使用模板标签语法:
// ✅ 正确: 模板标签语法(防止 SQL 注入)
const users = await sql`SELECT * FROM users WHERE email = ${email}`;
// ❌ 错误: 字符串拼接(SQL 注入风险)
const users = await sql('SELECT * FROM users WHERE email = ' + email);
Neon 事务 API (独特功能):
// 自动事务(查询数组)
const results = await sql.transaction([
sql`INSERT INTO users (name) VALUES (${name})`,
sql`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${accountId}`
]);
// 带回调的手动事务(用于复杂逻辑)
const result = await sql.transaction(async (sql) => {
const [user] = await sql`INSERT INTO users (name) VALUES (${name}) RETURNING id`;
await sql`INSERT INTO profiles (user_id) VALUES (${user.id})`;
return user;
});
Vercel Postgres 事务:
sql.connect() + 手动 BEGIN/COMMIT/ROLLBACKfinally 块中调用 client.release()(防止连接泄漏)Drizzle 事务:
await db.transaction(async (tx) => {
await tx.insert(users).values({ name, email });
await tx.insert(profiles).values({ userId: user.id });
});
连接字符串格式:
Pooled (serverless): postgresql://user:pass@ep-xyz-pooler.region.aws.neon.tech/db
Non-pooled (direct): postgresql://user:pass@ep-xyz.region.aws.neon.tech/db
何时使用每种:
-pooler.): 无服务器函数, 边缘函数, 高并发自动池化 (Neon/Vercel):
// 使用池化连接字符串时,两个包都会自动处理池化
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!); // 池化是自动的
连接限制:
关键:
Cloudflare Workers:
// src/index.ts
import { neon } from '@neondatabase/serverless';
export default {
async fetch(request: Request, env: Env) {
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`;
return Response.json(users);
}
};
# 部署
npx wrangler deploy
Vercel (Next.js API Route):
// app/api/users/route.ts
import { sql } from '@vercel/postgres';
export async function GET() {
const { rows } = await sql`SELECT * FROM users`;
return Response.json(rows);
}
# 部署
vercel deploy --prod
测试查询:
# 本地测试
curl http://localhost:8787/api/users
# 生产测试
curl https://your-app.workers.dev/api/users
要点:
✅ 必须做:
-pooler.)?sslmode=requiresql...``) 以防止 SQL 注入finally 块中调用 client.release()(仅限 Vercel Postgres 事务)POSTGRES_URL,Prisma 迁移时使用 POSTGRES_PRISMA_URL❌ 切勿做:
POSTGRES_URL_NON_POOLINGsslmode=require(连接将失败)此技能可预防 19 个已记录的问题 :
错误 : Error: connection pool exhausted 或 too many connections for role 来源 : https://github.com/neondatabase/serverless/issues/12 发生原因 : 在高并发无服务器环境中使用非池化连接字符串 预防 : 始终使用池化连接字符串(主机名中包含 -pooler.)。检查您的连接字符串格式。
错误 : Error: TCP connections are not supported in this environment 来源 : Cloudflare Workers 文档 发生原因 : 传统的 Postgres 客户端使用 TCP 套接字,这在边缘运行时中不可用 预防 : 使用 @neondatabase/serverless(基于 HTTP/WebSocket)而不是 pg 或 postgres.js 包。
错误 : 成功的 SQL 注入攻击或意外的查询结果 来源 : OWASP SQL 注入指南 发生原因 : 将用户输入拼接到 SQL 字符串中: sql('SELECT * FROM users WHERE id = ' + id) 预防 : 始终使用模板标签语法: sqlSELECT * FROM users WHERE id = ${id}``。模板标签自动转义值。
错误 : Error: connection requires SSL 或 FATAL: no pg_hba.conf entry 来源 : https://neon.tech/docs/connect/connect-securely 发生原因 : 连接字符串缺少 ?sslmode=require 参数 预防 : 始终在连接字符串后附加 ?sslmode=require。
错误 : 内存使用量逐渐增加,最终出现超时错误 来源 : https://github.com/vercel/storage/issues/45 发生原因 : 手动事务后忘记调用 client.release() 预防 : 始终使用 try/finally 块并在 finally 块中调用 client.release()。
错误 : Error: Connection string is undefined 或 connect ECONNREFUSED 来源 : https://vercel.com/docs/storage/vercel-postgres/using-an-orm 发生原因 : 使用 DATABASE_URL 而不是 POSTGRES_URL,或反之亦然 预防 : 查询时使用 POSTGRES_URL,Prisma 迁移时使用 POSTGRES_PRISMA_URL。
错误 : Error: Query timeout 或 Error: transaction timeout 来源 : https://neon.tech/docs/introduction/limits 发生原因 : 长时间运行的事务超过边缘函数超时时间(通常为 30 秒) 预防 : 保持事务简短(<5 秒),批量操作,或将复杂事务移至后台工作线程。
错误 : Error: PrismaClient is unable to be run in the browser 或模块解析错误 来源 : https://github.com/prisma/prisma/issues/18765 发生原因 : Prisma 需要具有文件系统访问权限的 Node.js 运行时 预防 : 为 Cloudflare Workers 使用 Drizzle ORM。Prisma 仅适用于 Vercel Edge/Node.js 运行时。
错误 : 调用 Neon API 时出现 Error: Unauthorized 来源 : https://neon.tech/docs/api/authentication 发生原因 : 缺少或无效的 NEON_API_KEY 环境变量 预防 : 在 Neon 仪表板 → Account Settings → API Keys 中创建 API 密钥,将其设置为环境变量。
错误 : 删除分支后出现 Error: database "xyz" does not exist 来源 : https://neon.tech/docs/guides/branching 发生原因 : 应用程序仍在使用已删除分支的连接字符串 预防 : 切换分支时更新 DATABASE_URL,分支更改后重启应用程序。
错误 : 空闲期后的第一个请求出现 Error: Query timeout,或 Connection terminated unexpectedly 来源 : Neon 文档 - 自动挂起 | GitHub Issue #168 | Changelog Dec 2025 发生原因 : Neon 在约 5 分钟不活动后自动挂起计算(免费层),导致约 1-2 秒的唤醒延迟或连接终止 预防 :
设置查询超时 >= 10 秒以应对冷启动
使用 HTTP 客户端 (neon()),它能透明地处理自动挂起
使用 Pool 处理连接终止错误:
import { Pool } from '@neondatabase/serverless';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// 关键: 处理连接终止错误 pool.on('error', (err) => { console.error('Unexpected database error:', err); // 实现重连逻辑或告警 });
生产配置 : 为获得一致的性能,禁用自动挂起
错误 : TypeScript 错误,如 Property 'x' does not exist on type 'User' 来源 : https://orm.drizzle.team/docs/generate 发生原因 : 数据库模式已更改但 Drizzle 类型未重新生成 预防 : 模式更改后运行 npx drizzle-kit generate,提交生成的文件。
错误 : Error: relation "xyz" already exists 或迁移版本冲突 来源 : https://neon.tech/docs/guides/branching#schema-migrations 发生原因 : 多个分支具有不同的迁移历史 预防 : 在主分支上运行迁移后创建分支,或在合并前重置分支模式。
错误 : Error: timestamp is outside retention window 来源 : https://neon.tech/docs/introduction/point-in-time-restore 发生原因 : 尝试从早于保留期的时间点恢复(免费层为 7 天) 预防 : 检查您计划的保留期,在允许的窗口内恢复。
错误 : Error: Invalid connection string 或查询性能缓慢 来源 : https://www.prisma.io/docs/orm/overview/databases/neon 发生原因 : 在无服务器环境中未使用 @prisma/adapter-neon 预防 : 安装 @prisma/adapter-neon 和 @neondatabase/serverless,配置 Prisma 使用基于 HTTP 的连接。
错误 : WebSocket is not defined 或 Next.js 15 预渲染时使用 use cache 超时 来源 : Neon 文档 - Prisma 指南 | GitHub Issue #181 发生原因 : Cloudflare Workers 等边缘运行时需要 HTTP 而不是 WebSocket 来执行 Pool 查询。Next.js 15 的 use cache 指令在使用带有 poolQueryViaFetch 的 Pool 时可能会超时。 预防 : 在边缘环境中使用 Pool 之前,设置 neonConfig.poolQueryViaFetch = true。
import { Pool, neonConfig } from '@neondatabase/serverless';
// 启用通过 HTTP fetch 的 Pool 查询(边缘环境必需)
neonConfig.poolQueryViaFetch = true;
const pool = new Pool({ connectionString: env.DATABASE_URL });
export default {
async fetch(request: Request, env: Env) {
// Pool.query() 现在使用 HTTP 而不是 WebSocket
const result = await pool.query('SELECT * FROM users');
return Response.json(result.rows);
}
};
注意事项 - Next.js 15use cache: 避免将 poolQueryViaFetch = true 与 use cache 指令一起使用 - 改用 neon() HTTP 客户端:
// ❌ 预渲染期间可能超时
import { Pool, neonConfig } from '@neondatabase/serverless';
neonConfig.poolQueryViaFetch = true;
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
async function getData() {
'use cache';
return await pool.query('SELECT * FROM data');
}
// ✅ 适用于预渲染
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
async function getData() {
'use cache';
return await sql`SELECT * FROM data`;
}
错误 : 在事务中使用 Promise.all() 时违反外键约束: insert or update on table violates foreign key constraint 来源 : Drizzle Issue #2200 发生原因 : 当在 Node.js v20+ 中使用 Neon 无服务器驱动程序和 Drizzle ORM 时,在事务内使用 Promise.all() 进行并行数据库操作会丢失事务上下文。顺序操作正常工作。这是 Neon 驱动程序在 Node v20 中会话处理特定的事务上下文管理问题。 预防 : 使用顺序操作,或切换到 postgres-js 驱动程序(不兼容边缘)用于 Node.js 环境。
// ❌ 在 Node v20 中使用 Neon 驱动程序失败
await db.transaction(async (tx) => {
const [user] = await tx.insert(users).values({ name: 'Alice' }).returning();
// 并行插入丢失事务上下文
await Promise.all([
tx.insert(userSettings).values({ userId: user.id, theme: 'dark' }),
tx.insert(userSettings).values({ userId: user.id, locale: 'en' })
]);
// 错误: 外键约束违规 (user.id 不可见)
});
// ✅ 有效 - 顺序执行
await db.transaction(async (tx) => {
const [user] = await tx.insert(users).values({ name: 'Alice' }).returning();
await tx.insert(userSettings).values({ userId: user.id, theme: 'dark' });
await tx.insert(userSettings).values({ userId: user.id, locale: 'en' });
});
// ✅ 替代方案 - 为 Node.js 使用 postgres-js 驱动程序(不兼容边缘)
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(connectionString);
const db = drizzle(client);
// 使用此驱动程序时 Promise.all() 正常工作
受影响配置 :
Promise.all() 进行并行插入错误 : ReferenceError: process is not defined 来源 : GitHub Issue #179 发生原因 : Neon 无服务器驱动程序在顶层无条件地访问 process.env.*,这会在 Slack 的 Deno 运行时等不提供 process.env 的沙盒化运行时中导致错误。 受影响环境 : Slack Deno 运行时, 没有 Node.js process 全局对象的沙盒化 JavaScript 环境 预防 : 目前尚无解决方法。用户必须:
process.envpg 并具有 Deno 兼容性)@neondatabase/serverless 和 pg 中修复(后者也访问 process.env)官方状态 : 未提供修复时间表的未解决问题。影响 Neon 驱动程序和底层的 pg 库。
破坏性变更 : v1.0.0 要求所有 SQL 查询使用标记模板语法。 来源 : Neon 博客文章 | GitHub Issue #3678
之前 (v0.x) :
const result = await sql("SELECT * FROM users WHERE id = $1", [userId]);
之后 (v1.0+) :
// 选项 1: 标记模板(推荐)
const result = await sql`SELECT * FROM users WHERE id = ${userId}`;
// 选项 2: .query() 方法用于参数化查询
const result = await sql.query("SELECT * FROM users WHERE id = $1", [userId]);
// 选项 3: .unsafe() 用于可信的原始 SQL(动态标识符)
const column = 'name';
const result = await sql`SELECT ${sql.unsafe(column)} FROM users`;
为何此变更 : v1.0.0 版本强制使用标记模板语法以防止 SQL 注入漏洞。函数调用语法 sql("...", [params]) 现在会引发运行时错误。
错误信息 :
This function can now be called only as a tagged-template function:
sql`SELECT ${value}`, not sql("SELECT $1", [value], options)
迁移清单 :
sql("...", [params]) 调用替换为标记模板better-auth 用户 : 如果使用 better-auth v1.3.4+ 和 Neon v1.0.0+,将 drizzle-orm 升级到 v0.40.1 或更高版本以解决兼容性:
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2",
"better-auth": "^1.3.4",
"drizzle-orm": "^0.40.1"
}
}
替代解决方法 : 使用 Kysely 代替 Drizzle 与 better-auth(无需更新 drizzle-orm 即可工作):
import { Kysely } from 'kysely';
import { Pool } from '@neondatabase/serverless';
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({ connectionString: process.env.DATABASE_URL })
})
});
HTTP 和 WebSocket 协议之间的性能特征差异显著。选择会影响延迟、吞吐量以及可用的 Postgres 功能。
| 使用场景 | 推荐 | 原因 |
|---|---|---|
| 每次请求单次查询 | HTTP (neon()) | 较低的初始延迟 (~37ms) |
| 2+ 次顺序查询 | WebSocket (Pool/Client) | 较低的每次查询延迟 (~5ms) |
| 并行独立查询 | HTTP | 更好的并行化 |
| 交互式事务 | WebSocket (必需) | 事务上下文必需 |
| 边缘函数 (单次执行) | HTTP | 无连接开销 |
| 长时间运行的工作线程 | WebSocket | 分摊连接成本 |
// HTTP: 最适合单次查询
import { neon } from '@neondatabase/serverless';
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`; // ~37ms
// WebSocket: 最适合多次顺序查询
import { Pool } from '@neondatabase/serverless';
const pool = new Pool({ connectionString: env.DATABASE_URL });
const client = await pool.connect(); // ~15ms 设置
try {
const user = await client.query('SELECT * FROM users WHERE id = $1', [1]); // ~5ms
const posts = await client.query('SELECT * FROM posts WHERE user_id = $1', [1]); // ~5ms
const comments = await client.query('SELECT * FROM comments WHERE user_id = $1', [1]); // ~5ms
// 总计: ~30ms (对比 HTTP 的 ~111ms)
} finally {
client.release();
}
HTTP 不支持 :
边缘环境中的 WebSocket 限制 :
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2"
}
}
{
"dependencies": {
"@vercel/postgres": "^0.10.0"
}
}
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2",
"drizzle-orm": "^0.44.7"
},
"devDependencies": {
"drizzle-kit": "^0.31.7"
},
"scripts": {
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio"
}
}
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './db/schema.ts',
out: './db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!
}
});
为何这些设置:
@neondatabase/serverless 是边缘兼容的(基于 HTTP/WebSocket)@vercel/postgres 在 Vercel 上提供零配置drizzle-orm 适用于所有运行时(Cloudflare Workers, Vercel Edge, Node.js)drizzle-kit 处理迁移和模式生成import { neon } from '@neondatabase/serverless';
interface Env { DATABASE_URL: string; }
export default {
async fetch(request: Request, env: Env) {
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`;
return Response.json(users);
}
};
'use server';
import { sql } from '@vercel/postgres';
export async function getUsers() {
const { rows } = await sql`SELECT * FROM users`;
return rows;
}
// db/index.ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!
Status : Production Ready Last Updated : 2026-01-21 Dependencies : None Latest Versions : @neondatabase/serverless@1.0.2, @vercel/postgres@0.10.0, drizzle-orm@0.45.1, drizzle-kit@0.31.8, neonctl@2.19.0
Option A: Neon Direct (multi-cloud, Cloudflare Workers, any serverless)
npm install @neondatabase/serverless
Option B: Vercel Postgres (Vercel-only, zero-config on Vercel)
npm install @vercel/postgres
Note : Both use the same Neon backend. Vercel Postgres is Neon with Vercel-specific environment setup.
Why this matters:
For Neon Direct:
# Sign up at https://neon.tech
# Create a project → Get connection string
# Format: postgresql://user:password@ep-xyz.region.aws.neon.tech/dbname?sslmode=require
For Vercel Postgres:
# In your Vercel project
vercel postgres create
vercel env pull .env.local # Automatically creates POSTGRES_URL and other vars
CRITICAL:
-pooler.region.aws.neon.tech)?sslmode=require parameterNeon Direct (Cloudflare Workers, Vercel Edge, Node.js):
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// Simple query
const users = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Transactions
const result = await sql.transaction([
sql`INSERT INTO users (name) VALUES (${name})`,
sql`SELECT * FROM users WHERE name = ${name}`
]);
Vercel Postgres (Next.js Server Actions, API Routes):
import { sql } from '@vercel/postgres';
// Simple query
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Transactions
const client = await sql.connect();
try {
await client.sql`BEGIN`;
await client.sql`INSERT INTO users (name) VALUES (${name})`;
await client.sql`COMMIT`;
} finally {
client.release();
}
CRITICAL:
sql...``) for automatic SQL injection protectionsql('SELECT * FROM users WHERE id = ' + id) ❌Choose based on your deployment platform:
Neon Direct (Cloudflare Workers, multi-cloud, direct Neon access):
npm install @neondatabase/serverless
Vercel Postgres (Vercel-specific, zero-config):
npm install @vercel/postgres
With ORM :
# Drizzle ORM (recommended for edge compatibility)
npm install drizzle-orm@0.45.1 @neondatabase/serverless@1.0.2
npm install -D drizzle-kit@0.31.8
# Prisma (Node.js only)
npm install prisma @prisma/client @prisma/adapter-neon @neondatabase/serverless
Key Points:
Option A: Neon Dashboard
postgresql://user:pass@ep-xyz-pooler.region.aws.neon.tech/db?sslmode=requireOption B: Vercel Dashboard
vercel env pull to get environment variables locallyOption C: Neon CLI (neonctl@2.19.0)
# Install CLI
npm install -g neonctl@2.19.0
# Authenticate
neonctl auth
# Create project and get connection string
neonctl projects create --name my-app
neonctl connection-string main
CRITICAL:
-pooler.region.aws.neon.tech)?sslmode=require in connection stringFor Neon Direct:
# .env or .env.local
DATABASE_URL="postgresql://user:password@ep-xyz-pooler.us-east-1.aws.neon.tech/neondb?sslmode=require"
For Vercel Postgres:
# Automatically created by `vercel env pull`
POSTGRES_URL="..." # Pooled connection (use this for queries)
POSTGRES_PRISMA_URL="..." # For Prisma migrations
POSTGRES_URL_NON_POOLING="..." # Direct connection (avoid in serverless)
POSTGRES_USER="..."
POSTGRES_HOST="..."
POSTGRES_PASSWORD="..."
POSTGRES_DATABASE="..."
For Cloudflare Workers (wrangler.jsonc):
{
"vars": {
"DATABASE_URL": "postgresql://user:password@ep-xyz-pooler.us-east-1.aws.neon.tech/neondb?sslmode=require"
}
}
Key Points:
POSTGRES_URL (pooled) for queriesPOSTGRES_PRISMA_URL for Prisma migrationsPOSTGRES_URL_NON_POOLING in serverless functionsOption A: Raw SQL
// scripts/migrate.ts
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
await sql`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
)
`;
Option B: Drizzle ORM (recommended)
// db/schema.ts
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
createdAt: timestamp('created_at').defaultNow()
});
// db/index.ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });
# Run migrations
npx drizzle-kit generate
npx drizzle-kit migrate
Option C: Prisma
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("POSTGRES_PRISMA_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now()) @map("created_at")
@@map("users")
}
npx prisma migrate dev --name init
CRITICAL:
CRITICAL - Template Tag Syntax Required:
// ✅ Correct: Template tag syntax (prevents SQL injection)
const users = await sql`SELECT * FROM users WHERE email = ${email}`;
// ❌ Wrong: String concatenation (SQL injection risk)
const users = await sql('SELECT * FROM users WHERE email = ' + email);
Neon Transaction API (Unique Features):
// Automatic transaction (array of queries)
const results = await sql.transaction([
sql`INSERT INTO users (name) VALUES (${name})`,
sql`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${accountId}`
]);
// Manual transaction with callback (for complex logic)
const result = await sql.transaction(async (sql) => {
const [user] = await sql`INSERT INTO users (name) VALUES (${name}) RETURNING id`;
await sql`INSERT INTO profiles (user_id) VALUES (${user.id})`;
return user;
});
Vercel Postgres Transactions:
sql.connect() + manual BEGIN/COMMIT/ROLLBACKclient.release() in finally block (prevents connection leaks)Drizzle Transactions:
await db.transaction(async (tx) => {
await tx.insert(users).values({ name, email });
await tx.insert(profiles).values({ userId: user.id });
});
Connection String Format:
Pooled (serverless): postgresql://user:pass@ep-xyz-pooler.region.aws.neon.tech/db
Non-pooled (direct): postgresql://user:pass@ep-xyz.region.aws.neon.tech/db
When to Use Each:
-pooler.): Serverless functions, edge functions, high-concurrencyAutomatic Pooling (Neon/Vercel):
// Both packages handle pooling automatically when using pooled connection string
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!); // Pooling is automatic
Connection Limits:
CRITICAL:
Cloudflare Workers:
// src/index.ts
import { neon } from '@neondatabase/serverless';
export default {
async fetch(request: Request, env: Env) {
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`;
return Response.json(users);
}
};
# Deploy
npx wrangler deploy
Vercel (Next.js API Route):
// app/api/users/route.ts
import { sql } from '@vercel/postgres';
export async function GET() {
const { rows } = await sql`SELECT * FROM users`;
return Response.json(rows);
}
# Deploy
vercel deploy --prod
Test Queries:
# Local test
curl http://localhost:8787/api/users
# Production test
curl https://your-app.workers.dev/api/users
Key Points:
✅ MUST DO:
-pooler. in hostname) for serverless?sslmode=require in connection stringssql...``) to prevent SQL injectionclient.release() in finally block (Vercel Postgres transactions only)POSTGRES_URL for queries, POSTGRES_PRISMA_URL for Prisma migrations❌ NEVER DO:
POSTGRES_URL_NON_POOLING in serverlesssslmode=require (connections will fail)This skill prevents 19 documented issues :
Error : Error: connection pool exhausted or too many connections for role Source : https://github.com/neondatabase/serverless/issues/12 Why It Happens : Using non-pooled connection string in high-concurrency serverless environment Prevention : Always use pooled connection string (with -pooler. in hostname). Check your connection string format.
Error : Error: TCP connections are not supported in this environment Source : Cloudflare Workers documentation Why It Happens : Traditional Postgres clients use TCP sockets, which aren't available in edge runtimes Prevention : Use @neondatabase/serverless (HTTP/WebSocket-based) instead of pg or postgres.js packages.
Error : Successful SQL injection attack or unexpected query results Source : OWASP SQL Injection Guide Why It Happens : Concatenating user input into SQL strings: sql('SELECT * FROM users WHERE id = ' + id) Prevention : Always use template tag syntax: sqlSELECT * FROM users WHERE id = ${id}``. Template tags automatically escape values.
Error : Error: connection requires SSL or FATAL: no pg_hba.conf entry Source : https://neon.tech/docs/connect/connect-securely Why It Happens : Connection string missing ?sslmode=require parameter Prevention : Always append ?sslmode=require to connection string.
Error : Gradually increasing memory usage, eventual timeout errors Source : https://github.com/vercel/storage/issues/45 Why It Happens : Forgetting to call client.release() after manual transactions Prevention : Always use try/finally block and call client.release() in finally block.
Error : Error: Connection string is undefined or connect ECONNREFUSED Source : https://vercel.com/docs/storage/vercel-postgres/using-an-orm Why It Happens : Using DATABASE_URL instead of POSTGRES_URL, or vice versa Prevention : Use POSTGRES_URL for queries, POSTGRES_PRISMA_URL for Prisma migrations.
Error : Error: Query timeout or Error: transaction timeout Source : https://neon.tech/docs/introduction/limits Why It Happens : Long-running transactions exceed edge function timeout (typically 30s) Prevention : Keep transactions short (<5s), batch operations, or move complex transactions to background workers.
Error : Error: PrismaClient is unable to be run in the browser or module resolution errors Source : https://github.com/prisma/prisma/issues/18765 Why It Happens : Prisma requires Node.js runtime with filesystem access Prevention : Use Drizzle ORM for Cloudflare Workers. Prisma works in Vercel Edge/Node.js runtimes only.
Error : Error: Unauthorized when calling Neon API Source : https://neon.tech/docs/api/authentication Why It Happens : Missing or invalid NEON_API_KEY environment variable Prevention : Create API key in Neon dashboard → Account Settings → API Keys, set as environment variable.
Error : Error: database "xyz" does not exist after deleting a branch Source : https://neon.tech/docs/guides/branching Why It Happens : Application still using connection string from deleted branch Prevention : Update DATABASE_URL when switching branches, restart application after branch changes.
Error : Error: Query timeout on first request after idle period, or Connection terminated unexpectedly Source : Neon Docs - Auto-suspend | GitHub Issue #168 | Changelog Dec 2025 Why It Happens : Neon auto-suspends compute after ~5 minutes of inactivity (free tier), causing ~1-2s wake-up delay or connection termination Prevention :
Set query timeout >= 10s to account for cold starts
Use HTTP client (neon()) which handles auto-suspend transparently
Handle connection termination errors with Pool:
import { Pool } from '@neondatabase/serverless';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// CRITICAL: Handle connection termination errors pool.on('error', (err) => { console.error('Unexpected database error:', err); // Implement reconnection logic or alerting });
Production Configuration : Disable auto-suspend for consistent performance
Error : TypeScript errors like Property 'x' does not exist on type 'User' Source : https://orm.drizzle.team/docs/generate Why It Happens : Database schema changed but Drizzle types not regenerated Prevention : Run npx drizzle-kit generate after schema changes, commit generated files.
Error : Error: relation "xyz" already exists or migration version conflicts Source : https://neon.tech/docs/guides/branching#schema-migrations Why It Happens : Multiple branches with different migration histories Prevention : Create branches AFTER running migrations on main, or reset branch schema before merging.
Error : Error: timestamp is outside retention window Source : https://neon.tech/docs/introduction/point-in-time-restore Why It Happens : Trying to restore from a timestamp older than retention period (7 days on free tier) Prevention : Check retention period for your plan, restore within allowed window.
Error : Error: Invalid connection string or slow query performance Source : https://www.prisma.io/docs/orm/overview/databases/neon Why It Happens : Not using @prisma/adapter-neon for serverless environments Prevention : Install @prisma/adapter-neon and @neondatabase/serverless, configure Prisma to use HTTP-based connection.
Error : WebSocket is not defined or timeout during Next.js 15 prerender with use cache Source : Neon Docs - Prisma Guide | GitHub Issue #181 Why It Happens : Edge runtimes like Cloudflare Workers require HTTP instead of WebSocket for Pool queries. Next.js 15's use cache directive can timeout when using Pool with poolQueryViaFetch. Prevention : Set neonConfig.poolQueryViaFetch = true before using Pool in edge environments.
import { Pool, neonConfig } from '@neondatabase/serverless';
// Enable Pool queries over HTTP fetch (required for edge)
neonConfig.poolQueryViaFetch = true;
const pool = new Pool({ connectionString: env.DATABASE_URL });
export default {
async fetch(request: Request, env: Env) {
// Pool.query() now uses HTTP instead of WebSocket
const result = await pool.query('SELECT * FROM users');
return Response.json(result.rows);
}
};
Caveat - Next.js 15use cache: Avoid poolQueryViaFetch = true with use cache directive - use neon() HTTP client instead:
// ❌ Can timeout during prerender
import { Pool, neonConfig } from '@neondatabase/serverless';
neonConfig.poolQueryViaFetch = true;
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
async function getData() {
'use cache';
return await pool.query('SELECT * FROM data');
}
// ✅ Works with prerender
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
async function getData() {
'use cache';
return await sql`SELECT * FROM data`;
}
Error : Foreign key constraint violations in transactions when using Promise.all(): insert or update on table violates foreign key constraint Source : Drizzle Issue #2200 Why It Happens : When using Node.js v20+ with Neon serverless driver and Drizzle ORM, parallel database operations within a transaction using Promise.all() lose transaction context. Sequential operations work correctly. This is a transaction context management issue specific to Neon driver's session handling in Node v20. Prevention : Use sequential operations or switch to postgres-js driver (not edge-compatible) for Node.js environments.
// ❌ FAILS in Node v20 with Neon driver
await db.transaction(async (tx) => {
const [user] = await tx.insert(users).values({ name: 'Alice' }).returning();
// Parallel inserts lose transaction context
await Promise.all([
tx.insert(userSettings).values({ userId: user.id, theme: 'dark' }),
tx.insert(userSettings).values({ userId: user.id, locale: 'en' })
]);
// Error: Foreign key constraint violation (user.id not visible)
});
// ✅ WORKS - Sequential execution
await db.transaction(async (tx) => {
const [user] = await tx.insert(users).values({ name: 'Alice' }).returning();
await tx.insert(userSettings).values({ userId: user.id, theme: 'dark' });
await tx.insert(userSettings).values({ userId: user.id, locale: 'en' });
});
// ✅ ALTERNATIVE - Use postgres-js driver for Node.js (not edge-compatible)
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const client = postgres(connectionString);
const db = drizzle(client);
// Promise.all() works correctly with this driver
Affected Configuration :
Promise.all() for parallel inserts in transactionError : ReferenceError: process is not defined Source : GitHub Issue #179 Why It Happens : The Neon serverless driver unconditionally accesses process.env.* at the top level, which causes errors in sandboxed runtimes like Slack's Deno runtime that don't provide process.env. Affected Environments : Slack Deno runtime, sandboxed JavaScript environments without Node.js process global Prevention : No workaround available yet. Users must either:
process.env in their runtimepg with Deno compatibility)@neondatabase/serverless and pg (which also accesses process.env)Official Status : Open issue with no fix timeline provided. Affects both Neon driver and underlying pg library.
Breaking Change : v1.0.0 requires tagged-template syntax for all SQL queries. Source : Neon Blog Post | GitHub Issue #3678
Before (v0.x) :
const result = await sql("SELECT * FROM users WHERE id = $1", [userId]);
After (v1.0+) :
// Option 1: Tagged template (recommended)
const result = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Option 2: .query() method for parameterized queries
const result = await sql.query("SELECT * FROM users WHERE id = $1", [userId]);
// Option 3: .unsafe() for trusted raw SQL (dynamic identifiers)
const column = 'name';
const result = await sql`SELECT ${sql.unsafe(column)} FROM users`;
Why this change : The v1.0.0 release enforces tagged-template syntax to prevent SQL injection vulnerabilities. Function-call syntax sql("...", [params]) now throws a runtime error.
Error Message :
This function can now be called only as a tagged-template function:
sql`SELECT ${value}`, not sql("SELECT $1", [value], options)
Migration Checklist :
sql("...", [params]) calls with tagged templatesbetter-auth Users : If using better-auth v1.3.4+ with Neon v1.0.0+, upgrade drizzle-orm to v0.40.1 or later to resolve compatibility:
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2",
"better-auth": "^1.3.4",
"drizzle-orm": "^0.40.1"
}
}
Alternative Workaround : Use Kysely instead of Drizzle with better-auth (works without drizzle-orm updates):
import { Kysely } from 'kysely';
import { Pool } from '@neondatabase/serverless';
const db = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({ connectionString: process.env.DATABASE_URL })
})
});
Source : Neon Blog - HTTP vs WebSockets
Performance characteristics differ significantly between HTTP and WebSocket protocols. The choice affects latency, throughput, and what Postgres features are available.
| Use Case | Recommended | Reason |
|---|---|---|
| Single query per request | HTTP (neon()) | Lower initial latency (~37ms) |
| 2+ sequential queries | WebSocket (Pool/Client) | Lower per-query latency (~5ms) |
| Parallel independent queries | HTTP | Better parallelization |
| Interactive transactions | WebSocket (required) | Required for transaction context |
| Edge Functions (single-shot) | HTTP | No connection overhead |
| Long-running workers | WebSocket | Amortize connection cost |
// HTTP: Best for single queries
import { neon } from '@neondatabase/serverless';
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`; // ~37ms
// WebSocket: Best for multiple sequential queries
import { Pool } from '@neondatabase/serverless';
const pool = new Pool({ connectionString: env.DATABASE_URL });
const client = await pool.connect(); // ~15ms setup
try {
const user = await client.query('SELECT * FROM users WHERE id = $1', [1]); // ~5ms
const posts = await client.query('SELECT * FROM posts WHERE user_id = $1', [1]); // ~5ms
const comments = await client.query('SELECT * FROM comments WHERE user_id = $1', [1]); // ~5ms
// Total: ~30ms (vs ~111ms with HTTP)
} finally {
client.release();
}
HTTP does NOT support :
WebSocket limitations in edge :
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2"
}
}
{
"dependencies": {
"@vercel/postgres": "^0.10.0"
}
}
{
"dependencies": {
"@neondatabase/serverless": "^1.0.2",
"drizzle-orm": "^0.44.7"
},
"devDependencies": {
"drizzle-kit": "^0.31.7"
},
"scripts": {
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio"
}
}
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './db/schema.ts',
out: './db/migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!
}
});
Why these settings:
@neondatabase/serverless is edge-compatible (HTTP/WebSocket-based)@vercel/postgres provides zero-config on Verceldrizzle-orm works in all runtimes (Cloudflare Workers, Vercel Edge, Node.js)drizzle-kit handles migrations and schema generationimport { neon } from '@neondatabase/serverless';
interface Env { DATABASE_URL: string; }
export default {
async fetch(request: Request, env: Env) {
const sql = neon(env.DATABASE_URL);
const users = await sql`SELECT * FROM users`;
return Response.json(users);
}
};
'use server';
import { sql } from '@vercel/postgres';
export async function getUsers() {
const { rows } = await sql`SELECT * FROM users`;
return rows;
}
// db/index.ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });
// Usage: Type-safe queries with JOINs
const postsWithAuthors = await db
.select({ postId: posts.id, authorName: users.name })
.from(posts)
.leftJoin(users, eq(posts.userId, users.id));
See Step 5 for Neon's unique transaction API (array syntax or callback syntax)
# Create branch for PR
neonctl branches create --project-id my-project --name pr-123 --parent main
# Get connection string for branch
BRANCH_URL=$(neonctl connection-string pr-123)
# Use in Vercel preview deployment
vercel env add DATABASE_URL preview
# Paste $BRANCH_URL
# Delete branch when PR is merged
neonctl branches delete pr-123
# .github/workflows/preview.yml
name: Create Preview Database
on:
pull_request:
types: [opened, synchronize]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- name: Create Neon Branch
run: |
BRANCH_NAME="pr-${{ github.event.pull_request.number }}"
neonctl branches create --project-id ${{ secrets.NEON_PROJECT_ID }} --name $BRANCH_NAME
BRANCH_URL=$(neonctl connection-string $BRANCH_NAME)
- name: Deploy to Vercel
env:
DATABASE_URL: ${{ steps.branch.outputs.url }}
run: vercel deploy --env DATABASE_URL=$DATABASE_URL
When to use : Want isolated database for each PR/preview deployment
setup-neon.sh - Creates Neon database and outputs connection string
chmod +x scripts/setup-neon.sh
./scripts/setup-neon.sh my-project-name
test-connection.ts - Verifies database connection and runs test query
npx tsx scripts/test-connection.ts
references/connection-strings.md - Complete guide to connection string formats, pooled vs non-pooledreferences/drizzle-setup.md - Step-by-step Drizzle ORM setup with Neonreferences/prisma-setup.md - Prisma setup with Neon adapterreferences/branching-guide.md - Comprehensive guide to Neon database branchingreferences/migration-strategies.md - Migration patterns for different ORMs and toolsreferences/common-errors.md - Extended troubleshooting guideWhen Claude should load these :
connection-strings.md when debugging connection issuesdrizzle-setup.md when user wants to use Drizzle ORMprisma-setup.md when user wants to use Prismabranching-guide.md when user asks about preview environments or database branchingcommon-errors.md when encountering specific error messagesassets/schema-example.sql - Example database schema with users, posts, commentsassets/drizzle-schema.ts - Complete Drizzle schema templateassets/prisma-schema.prisma - Complete Prisma schema templateNeon provides git-like database branching:
# Create branch from main
neonctl branches create --name dev --parent main
# Create from point-in-time (PITR restore)
neonctl branches create --name restore --parent main --timestamp "2025-10-28T10:00:00Z"
# Get connection string for branch
neonctl connection-string dev
# Delete branch
neonctl branches delete feature
Key Features:
Connection Pool Monitoring:
Query Optimization:
Security:
Required :
@neondatabase/serverless@^1.0.2 - Neon serverless Postgres client (HTTP/WebSocket-based)@vercel/postgres@^0.10.0 - Vercel Postgres client (alternative to Neon direct, Vercel-specific)Optional :
drizzle-orm@^0.44.7 - TypeScript ORM (edge-compatible, recommended)drizzle-kit@^0.31.7 - Drizzle schema migrations and introspection@prisma/client@^6.10.0 - Prisma ORM (Node.js only, not edge-compatible)@prisma/adapter-neon@^6.10.0 - Prisma adapter for Neon serverlessneonctl@^2.19.0 - Neon CLI for database managementzod@^3.24.0 - Schema validation for input sanitization/github/neondatabase/serverless, /github/vercel/storage{
"dependencies": {
"@neondatabase/serverless": "^1.0.2",
"@vercel/postgres": "^0.10.0",
"drizzle-orm": "^0.45.1"
},
"devDependencies": {
"drizzle-kit": "^0.31.8",
"neonctl": "^2.19.0"
}
}
Latest Prisma (if needed) :
{
"dependencies": {
"@prisma/client": "^6.10.0",
"@prisma/adapter-neon": "^6.10.0"
},
"devDependencies": {
"prisma": "^6.10.0"
}
}
This skill is based on production deployments of Neon and Vercel Postgres:
Error: connection pool exhaustedSolution :
-pooler.region.aws.neon.tech)Error: TCP connections are not supportedSolution :
@neondatabase/serverless instead of pg or postgres.jsError: database "xyz" does not existSolution :
DATABASE_URL points to correct databaseSolution :
PrismaClient is unable to be run in the browserSolution :
@prisma/adapter-neonSolution :
neonctl branches reset feature --parent mainError : Warning: @neondatabase/serverless can only connect to remote Neon/Vercel Postgres/Supabase instances through a websocket Source : GitHub Discussion #12508 Solution : This warning is informational and can be safely ignored. Migrations work correctly despite the warning. The warning exists to inform users that WebSocket protocol is being used, which helps with debugging if something goes wrong. Adding pg as a dev dependency eliminates the warning but is unnecessary.
Error : NeonDbError: Error connecting to database: fetch failed [cause]: SocketError: other side closed Source : GitHub Issue #146 comment Solution : Some VPNs block WebSocket or fetch connections to Neon's endpoints. This occurs primarily during development (localhost) with Next.js 14+ server actions. Disable VPN and test, or whitelist Neon domains in VPN configuration:
# Whitelist these domains in VPN:
*.neon.tech
*.aws.neon.tech
Use this checklist to verify your setup:
@neondatabase/serverless or @vercel/postgres)-pooler.)?sslmode=requireDATABASE_URL or POSTGRES_URL)sql...``)Questions? Issues?
references/common-errors.md for extended troubleshootingsslmode=require is in connection stringscripts/test-connection.tsLast verified : 2026-01-21 | Skill version : 2.0.0 | Changes : Added 4 new issues (#16-#19: poolQueryViaFetch, Node v20 transactions, process.env sandboxing); added Migration Guide (v0.x→v1.0+); added Performance & Protocol Selection section; expanded Issue #11 with auto-suspend handling and production config; added TIER 2 community-sourced troubleshooting (WebSocket warning, VPN blocking)
Weekly Installs
363
Repository
GitHub Stars
643
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code301
gemini-cli241
opencode238
cursor227
antigravity217
codex211
Supabase Postgres 最佳实践指南 - 8大类别性能优化规则与SQL示例
57,300 周安装