Connection pooling
Use Prisma Postgres connection pooling for concurrent application traffic.
Prisma Postgres routes application traffic through a tenant-isolated PgBouncer instance running in transactional pool mode. This page covers how pooling works, what limits apply, and when to bypass it. For connection string setup and runtime-specific guidance, see Connecting to your database.
Connection limits
| Free | Starter | Pro | Business | |
|---|---|---|---|---|
| Pooled connections | 50 | 50 | 250 | 500 |
| Direct connections | 10 | 10 | 50 | 100 |
These are concurrent connection limits per plan. 5 direct connections are reserved for platform operations (maintenance, monitoring) and are not available to your workload.
Idle pooled connections are closed after 60 minutes. Compare plans on the Prisma pricing page.
How the pooler works
Application → Connection Proxy → PgBouncer (per tenant, transactional mode) → DatabaseYour application opens a connection to the pooled hostname (pooled.db.prisma.io). The pooler multiplexes many client connections onto a smaller number of database connections, assigning a backend connection for the duration of each transaction and returning it to the pool when the transaction completes.
Because PgBouncer operates in transactional mode:
- Session state does not persist between transactions. Any
SETcommands, prepared statements, advisory locks, or temporary tables are lost after each transaction boundary. If your workload depends on session state, use a direct connection. - Queries are limited to 10 minutes. Queries exceeding this timeout are terminated. For long-running jobs, use a direct connection.
When to use each connection type
Use pooled connections (pooled.db.prisma.io) for all application traffic: API handlers, background workers, serverless functions, edge runtimes.
Use direct connections (db.prisma.io) for:
- Migrations (
prisma migrate deploy,prisma db push) - Schema introspection (
prisma db pull) - Prisma Studio and admin tooling
pg_dump/pg_restoreLISTEN/NOTIFY- Workloads that use session-level
SETcommands or prepared statements outside transactions - Queries that may exceed 10 minutes
Getting this wrong has asymmetric failure modes. Running migrations through the pooler produces clear errors (lock failures, session state errors). Running application traffic over direct connections works fine at low concurrency but causes silent connection exhaustion under load. The kind of issue that only surfaces in production.
Troubleshooting
"Too many connections" or connection limit errors
Your application is exceeding the pooled connection limit for your plan. Common causes:
- Creating a new database client per request. Prisma Client should be instantiated once and reused across requests. In serverless environments, instantiate the client outside the handler function so it persists across warm invocations.
- Too many concurrent serverless instances. Each function instance holds its own connection(s). If your platform auto-scales to 200 instances and your plan allows 50 pooled connections, you will hit the limit. Cap concurrency at the platform level or upgrade your plan.
- Using the direct hostname for application traffic. Direct connection limits are much lower (10–100 depending on plan). Switch application traffic to
pooled.db.prisma.io.
Migration fails with lock, session, or prepared statement errors
The pooled connection string was used for a migration or admin workflow that requires session continuity. Switch to the direct hostname (db.prisma.io) for all Prisma CLI commands and admin tooling.
Session state not persisting between queries
Expected behavior in transactional pool mode. The pooler returns the backend connection to the pool after each transaction, so SET commands, temporary tables, and prepared statements do not carry over. Use a direct connection for session-dependent workloads.
Query killed after 10 minutes
Pooled connections enforce a 10-minute query timeout. Break the query into smaller batches, or run it over a direct connection where no timeout is enforced.