patternjavascriptprismaCritical
Prisma connection pool: sizing and PgBouncer compatibility
Viewed 0 times
prismaconnection poolPgBouncerserverlessmax_connectionsconnection_limitPrisma Acceleratesingleton
Error Messages
Problem
Prisma's default connection pool (based on database CPU count) is too large for serverless environments where each function instance creates its own pool, exhausting PostgreSQL's max_connections. With PgBouncer the pool settings conflict.
Solution
For serverless: set connection_limit=1 in the DATABASE_URL and use an external pooler (PgBouncer, Supabase Pooler, or Prisma Accelerate). For PgBouncer in transaction mode: disable prepared statements with pgbouncer=true in the URL.
Why
Each serverless invocation that calls new PrismaClient() creates a new pool. With 100 concurrent functions each holding a pool of 5, you hit 500 connections. PostgreSQL defaults to max_connections=100.
Gotchas
- PgBouncer in transaction mode does not support prepared statements — add ?pgbouncer=true to disable them
- connection_limit=1 means queries serialize within a single function instance — fine for serverless, bad for long-running servers
- Prisma Accelerate (edge proxy) handles pooling outside the function but adds network latency
- Never instantiate PrismaClient inside a request handler — use a module-level singleton
Code Snippets
Prisma singleton and serverless connection URL
// lib/prisma.ts — module-level singleton prevents pool exhaustion
import { PrismaClient } from '@prisma/client';
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
// .env for serverless with PgBouncer in transaction mode
// DATABASE_URL="postgresql://user:pass@host:6432/db?connection_limit=1&pgbouncer=true"Revisions (0)
No revisions yet.