pg-serverless-doctor
v0.1.0
Published
Statically diagnose serverless Postgres connection/pooling misconfigs (Supabase, Neon x Prisma, Drizzle). No DB connection, no credentials, reads local files only.
Maintainers
Readme
pg-serverless-doctor
Catch the serverless Postgres config bug before it pages you at 2 a.m.
A tiny CLI that statically reads your project's config files and flags the connection/pooling misconfigurations that cause the classic serverless failures:
prepared statement "s0" already existsFATAL: too many connections/ PrismaP2024- migrations failing through a transaction pooler (missing
DIRECT_URL) - pooled-vs-direct URL confusion on Supabase and Neon
Supports Supabase and Neon × Prisma and Drizzle.
No DB. No credentials. Runs locally.
This is the whole point. pg-serverless-doctor never connects to a database,
never makes a network request, and never transmits a credential. It only reads
local files (.env, schema.prisma, package.json, …) in your current directory.
- Zero runtime dependencies — plain Node.js ESM. Audit the whole thing in a couple of minutes.
- Trust barrier zero — nothing leaves your machine, so it's safe to run
against a repo that has production connection strings in
.env.
Usage
# in your project root
npx pg-serverless-doctor
# or point it at a directory
npx pg-serverless-doctor ./apps/web
# machine-readable output for CI (exits non-zero if any ERROR)
npx pg-serverless-doctor --jsonNo install, no build step. Requires Node >= 18.
What it scans
All optional — missing files are simply skipped:
.env · .env.local · schema.prisma · drizzle.config.* · package.json · vercel.json · netlify.toml
What it catches
| Rule | Level | What it detects |
|------|-------|-----------------|
| R1 | ERROR / WARN | DATABASE_URL is a transaction pooler (Supabase :6543 or Neon -pooler). Prisma without pgbouncer=true → ERROR. Drizzle → WARN (prepare:false lives in runtime code, can't be verified statically). Remediation includes the version-dependent hedge: on PgBouncer ≥ 1.21 / newer Supavisor you may need to remove pgbouncer=true. |
| R2 | ERROR | Prisma datasource.url resolves to a pooler host but there is no directUrl in the schema and no DIRECT_URL in env — migrations / introspection break through the pooler. |
| R3 | WARN | DATABASE_URL is a direct connection (:5432, no -pooler), serverless markers are present (vercel.json / netlify.toml / @vercel/* / next), and there is no connection_limit — risk of "too many connections". |
| R4 | INFO | Neon direct host missing sslmode=require / connect_timeout. |
Honesty
The tool never prints a false "PASS" for something it cannot verify from files
alone. Drizzle's prepare:false, the value of connection_limit, and your
PgBouncer/Supavisor version are runtime facts — for those it says WARN /
confirm manually rather than pretending everything is fine.
Example output
🔎 pg-serverless-doctor (static scan — no DB connection, no credentials sent)
scanned: .env, schema.prisma, package.json
orm: Prisma
✖ ERROR R1 transaction pooler without pgbouncer=true
where: .env DATABASE_URL → aws-0-us-east-1.pooler.supabase.com:6543
Fix: Prisma over a transaction pooler must disable prepared statements:
append `?pgbouncer=true` to DATABASE_URL. If you are on PgBouncer >=1.21 /
newer Supavisor you may instead need to REMOVE it — version-dependent.
docs: https://www.npmjs.com/package/pg-serverless-doctor#r1
1 error, 0 warnings, 0 info, 1 passExit codes
0— no errors (warnings / info may still be present)1— at least one ERROR2— bad CLI usage (unknown flag)
Roadmap → Pro pack
This free tool tells you what's wrong. The Pro pack gives you the copy-paste
fixes: provider × runtime (Vercel / Lambda / edge) dual-URL .env + config
templates, a connection_limit calculator, and serverless-safe client singletons.
Want the Pro pack? → Join the waitlist in GitHub Discussions. ⭐ Star & Watch the repo to get notified when it ships.
License
MIT
