Claude-skills prisma-connection-pool-exhaustion
git clone https://github.com/ckorhonen/claude-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/ckorhonen/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/continuous-learning/examples/prisma-connection-pool-exhaustion" ~/.claude/skills/ckorhonen-claude-skills-prisma-connection-pool-exhaustion && rm -rf "$T"
skills/continuous-learning/examples/prisma-connection-pool-exhaustion/SKILL.mdPrisma Connection Pool Exhaustion in Serverless
Problem
Serverless functions create a new Prisma client instance on each cold start. Each instance opens multiple database connections (default: 5 per instance). With many concurrent requests, this quickly exhausts the database's connection limit (often 20-100 for managed databases).
Context / Trigger Conditions
This skill applies when you see:
P2024: Timed out fetching a new connection from the connection pool- PostgreSQL:
FATAL: too many connections for role "username" - MySQL:
Too many connections - Works fine locally with
but fails in productionnpm run dev - Errors appear during traffic spikes, then resolve
- Database dashboard shows connections at or near limit
Environment indicators:
- Deploying to Vercel, AWS Lambda, Netlify Functions, or similar
- Using Prisma with PostgreSQL, MySQL, or another connection-based database
- Database is managed (PlanetScale, Supabase, Neon, RDS, etc.)
Solution
Step 1: Use Connection Pooling Service
The recommended solution is to use a connection pooler like PgBouncer or Prisma Accelerate, which sits between your serverless functions and the database.
For Supabase:
# .env # Use the pooled connection string (port 6543, not 5432) DATABASE_URL="postgresql://user:pass@db.xxx.supabase.co:6543/postgres?pgbouncer=true"
For Neon:
# .env DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/dbname?sslmode=require" # Neon has built-in pooling
For Prisma Accelerate:
npx prisma generate --accelerate
Step 2: Configure Prisma Connection Limits
In your
schema.prisma:
datasource db { provider = "postgresql" url = env("DATABASE_URL") // Limit connections per Prisma instance relationMode = "prisma" }
In your connection URL or Prisma client:
// lib/prisma.ts import { PrismaClient } from '@prisma/client' const globalForPrisma = global as unknown as { prisma: PrismaClient } export const prisma = globalForPrisma.prisma || new PrismaClient({ datasources: { db: { url: process.env.DATABASE_URL + '?connection_limit=1' } } }) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
Step 3: Singleton Pattern (Development)
Prevent hot-reload from creating new clients:
// lib/prisma.ts import { PrismaClient } from '@prisma/client' const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined } export const prisma = globalForPrisma.prisma ?? new PrismaClient() if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
Step 4: URL Parameters
Add these to your connection string:
?connection_limit=1&pool_timeout=20&connect_timeout=10
: One connection per serverless instanceconnection_limit=1
: Wait up to 20s for available connectionpool_timeout=20
: Fail fast if can't connect in 10sconnect_timeout=10
Verification
After applying fixes:
- Deploy to production
- Run a load test:
npx autocannon -c 100 -d 30 https://your-app.com/api/test - Check database dashboard—connections should stay within limits
- No more P2024 errors in logs
Example
Before (error under load):
[ERROR] PrismaClientKnownRequestError: Invalid `prisma.user.findMany()` invocation: Timed out fetching a new connection from the connection pool.
After (with connection pooling):
# Using Supabase pooler URL DATABASE_URL="postgresql://...@db.xxx.supabase.co:6543/postgres?pgbouncer=true&connection_limit=1"
Database connections stable at 10-15 even under heavy load.
Notes
- Different managed databases have different pooling solutions—check your provider's docs
- PlanetScale (MySQL) uses a different architecture and doesn't have this issue
is aggressive; start there and increase if you see latencyconnection_limit=1- The singleton pattern only helps in development; in production serverless, each instance is isolated
- If using Prisma with Next.js API routes, each route invocation may be a separate serverless function
- Consider Prisma Accelerate for built-in caching + pooling: https://www.prisma.io/accelerate