Timed out fetching a new connection from the connection pool. (More info: https://pris.ly/d/connection-pool)
appears when:When a Vercel serverless function holds its Prisma client open through many concurrent requests without a shared pooler like PgBouncer or Accelerate
Prisma connection pool timeout
Serverless spawns a new Prisma client per cold start. Without PgBouncer or the Neon driver, Postgres runs out of connections and requests queue until Prisma gives up.
pgbouncer=true&connection_limit=1 in DATABASE_URL, store the PrismaClient on globalThis so dev reloads do not multiply pools, and use Neon's serverless driver or Prisma Accelerate when you need higher concurrency.Quick fix for Prisma connection pool timeout
01// lib/db.ts — canonical Prisma client for serverless + Vercel02import { PrismaClient } from "@prisma/client";03 04const globalForPrisma = globalThis as unknown as {05 prisma: PrismaClient | undefined;06};07 08export const db =09 globalForPrisma.prisma ??10 new PrismaClient({11 log: process.env.NODE_ENV === "development" ? ["error", "warn"] : ["error"],12 });13 14if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;15 16// .env.production — must include pgbouncer=true and connection_limit=117// DATABASE_URL="postgres://user:pass@pooler.supabase.com:6543/db?pgbouncer=true&connection_limit=1"18// DIRECT_URL="postgres://user:pass@db.supabase.co:5432/db" # used only for migrations19//20// prisma/schema.prisma21// datasource db {22// provider = "postgresql"23// url = env("DATABASE_URL")24// directUrl = env("DIRECT_URL")25// }Deeper fixes when the quick fix fails
01 · Neon serverless driver — best for edge runtime
01// lib/db.ts — Prisma with @neondatabase/serverless over WebSockets02import { PrismaClient } from "@prisma/client";03import { PrismaNeon } from "@prisma/adapter-neon";04import { Pool } from "@neondatabase/serverless";05 06const pool = new Pool({ connectionString: process.env.DATABASE_URL });07const adapter = new PrismaNeon(pool);08 09const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };10 11export const db =12 globalForPrisma.prisma ??13 new PrismaClient({ adapter });14 15if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;02 · Prisma Accelerate — managed pool and edge cache
01// lib/db.ts — Accelerate via the Prisma extension02import { PrismaClient } from "@prisma/client/edge";03import { withAccelerate } from "@prisma/extension-accelerate";04 05const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };06 07export const db =08 globalForPrisma.prisma ??09 new PrismaClient().$extends(withAccelerate()) as unknown as PrismaClient;10 11if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = db;12 13// .env — DATABASE_URL is an Accelerate URL starting with prisma://14// DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=..."15// DIRECT_URL="postgres://user:pass@db.neon.tech:5432/db"03 · Kill long-running queries in Postgres
01-- Supabase SQL editor — cancel any connection idle in transaction for > 60s02select pg_terminate_backend(pid)03from pg_stat_activity04where state = 'idle in transaction'05 and (now() - state_change) > interval '60 seconds';06 07-- Add as a pg_cron job to run every minute08select cron.schedule(09 'kill-idle-in-tx',10 '* * * * *',11 $$select pg_terminate_backend(pid) from pg_stat_activity where state = 'idle in transaction' and (now() - state_change) > interval '60 seconds';$$12);Why AI-built apps hit Prisma connection pool timeout
Prisma opens a dedicated TCP connection pool per PrismaClient instance. Default pool size is num_physical_cpus * 2 + 1. On a Vercel serverless function that is usually three. Each concurrent invocation runs in its own Node process with its own client and its own pool of three. Ten concurrent requests means thirty Postgres connections. Postgres on Supabase free tier allows sixty total. Three busy API routes saturate the database and Prisma's local pool waits; when the wait exceeds ten seconds it throws Timed out fetching a new connection from the connection pool.
AI builders scaffold const prisma = new PrismaClient() at the top of every file. In development, Next.js hot-reloads on every edit, each reload spawns a new client, and within minutes you have fifty zombie connections that Postgres never closed. Dev-time symptoms match production-time symptoms and both are the same root cause.
The fix for production is a connection pooler outside Prisma. PgBouncer in transaction mode multiplexes many client connections over a small pool of real Postgres connections. Supabase ships a hosted PgBouncer on port 6543. Neon ships a pgbouncer-compatible pooler at pooler.neon.tech. Prisma respects pgbouncer=true in the connection string, which disables prepared statements (PgBouncer transaction mode does not support them) and sets connection_limit=1 so Prisma takes only one connection from the pooler per invocation.
The fix for dev-time pool exhaustion is the global singleton pattern. Store the PrismaClient on globalThis in non-production environments so hot reloads find the existing client and do not open a new pool. In production this is a no-op because each invocation is a fresh Node process. This pattern is well-known but AI-generated code often skips it.
When PgBouncer transaction mode is not enough — for example you use $transaction blocks with long-running queries — switch to the Neon serverless driver (which talks to Neon over WebSockets and scales horizontally) or Prisma Accelerate (which adds a managed pool plus an edge cache). Both are drop-in for most apps.
Prisma connection pool timeout by AI builder
How often each AI builder ships this error and the pattern that produces it.
| Builder | Frequency | Pattern |
|---|---|---|
| Lovable | Every Prisma scaffold | new PrismaClient() at top of every file — dev reloads multiply pools |
| Bolt.new | Common | No pgbouncer=true in DATABASE_URL — goes direct to port 5432 |
| v0 | Common | No singleton pattern — hot reload eats all Postgres connections |
| Cursor | Sometimes | Calls fetch() inside db.$transaction — holds connection for seconds |
| Replit Agent | Rare | Ignores DIRECT_URL — migrations fail through PgBouncer transaction mode |
Related errors we fix
Stop Prisma connection pool timeout recurring in AI-built apps
- →Always route Prisma through PgBouncer (port 6543) or the Neon serverless driver in production.
- →Instantiate PrismaClient exactly once via the globalThis singleton pattern.
- →Never put fetch() or any async non-DB call inside a $transaction block.
- →Run a 100-concurrent-user load test before every deploy that touches DB code.
- →Add a pg_cron job that kills idle-in-transaction connections older than 60 seconds.
Still stuck with Prisma connection pool timeout?
Prisma connection pool timeout questions
Why does Prisma keep hitting connection pool timeouts on Vercel?+
What connection_limit should I set on Prisma for serverless?+
Should I use Prisma Accelerate or PgBouncer?+
What is a global Prisma instance and why do I need it?+
How long does a Prisma pool fix take?+
Ship the fix. Keep the fix.
Emergency Triage restores service in 48 hours. Break the Fix Loop rebuilds CI so this error cannot ship again.
Hyder Shah leads Afterbuild Labs, shipping production rescues for apps built in Lovable, Bolt.new, Cursor, Replit, v0, and Base44. our rescue methodology.