Prisma P2024: “Timed out fetching a new connection from the connection pool”.
P2024 means a query waited longer than Prisma’s pool timeout (10 seconds by default) for one of the pool’s connections. Postgres did not refuse you. More queries ran at once than the pool holds, or slow queries kept connections busy. Use one PrismaClient, size the pool to what the database allows, and fix slow queries before raising the timeout.
Facts checked
Read the two numbers in the message
The full error from Prisma 6 and older is:
- connection limit is the size of this client’s pool. If you never set it, Prisma 6 used physical CPU cores × 2 + 1. The 9 above is a 4-core machine.
- connection pool timeout is how long, in seconds, a query waits in Prisma’s queue for a free connection before it fails with P2024. The default is 10.
Timed out fetching a new connection from the connection pool.
(Current connection pool timeout: 10, connection limit: 9)The usual causes, most common first
- Several PrismaClient instances. Each
new PrismaClient()has its own pool. A client created per request, per module, or on every hot reload innext devmultiplies connections until the database or the pool runs out. Keep one client per process (code below). - A burst wider than the pool.
Promise.allover 50 queries, or a page that fires 30 lookups at once, all need a connection at the same time. With a pool of 9, 41 wait. If the first 9 are slow, the rest time out. - Slow queries holding connections. A 4-second query keeps its connection for 4 seconds. Ten of those and a 10-connection pool is full. Raising the limit hides it until traffic grows. Find them with pg_stat_statements.
- Long interactive transactions.
prisma.$transaction(async (tx) => …)holds one connection from start to finish, including anyfetchor other slow work you do inside it. Do the slow part outside the transaction. - A pool sized for the wrong machine. Prisma 6’s default counts the CPU cores the process can see. Move the same app to a bigger host and the pool grows with it, possibly past what the database allows.
// lib/prisma.ts: one client for the whole process
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
// Dev hot reload would otherwise create a new client (and pool) per reload
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;Prisma 7 moved the pool to the driver
In Prisma ORM 7, Postgres goes through a driver adapter such as @prisma/adapter-pg, and the pool is the driver’s. Prisma’s own docs say the defaults “now come from the driver itself”. For pg that changes two things you may be relying on: the pool holds 10 connections whatever the CPU count, and the acquire timeout is 0, which means a query waits forever instead of failing.
So on Prisma 7 with pg you may never see P2024. Pool exhaustion shows up as requests that hang. If you set connectionTimeoutMillis, the error becomes pg’s timeout exceeded when trying to connect.
| Prisma 6 (URL parameter) | Default | Prisma 7 with pg (adapter field) | Default |
|---|---|---|---|
connection_limit † † | Physical cores × 2 + 1 | max | 10 |
pool_timeout † † † | 10 s | connectionTimeoutMillis | 0 (no timeout) |
max_idle_connection_lifetime † † | 300 s | idleTimeoutMillis | 10 s |
| P2024 on timeout † † | Yes | timeout exceeded when trying to connect | Only once a timeout is set |
† Competitor details come from each vendor’s own published pages on the dates shown; prices and plans change, so check the vendor before you decide. `connection_limit` (2026-10-29) · `connection_limit` (2026-10-29) · `pool_timeout` (2026-10-29) · `pool_timeout` (2026-10-29) · `pool_timeout` (2026-10-29) · `max_idle_connection_lifetime` (2026-10-29) · `max_idle_connection_lifetime` (2026-10-29) · P2024 on timeout (2026-10-29) · P2024 on timeout (2026-10-29)
Size the pool, in Prisma 6 and 7
Prisma’s guidance for a long-running server is to start from the default pool divided by the number of app instances. In practice, work backwards from the database: take the connections it allows, subtract what everything else needs (migrations, a second process, psql), and give the rest to the app.
If your platform injects DATABASE_URL, you don’t have to edit the variable. Set the parameters in code:
// Prisma 6: set the pool in code when DATABASE_URL is injected for you
const url = new URL(process.env.DATABASE_URL!);
url.searchParams.set("connection_limit", "10");
url.searchParams.set("pool_timeout", "20"); // seconds
export const prisma = new PrismaClient({ datasourceUrl: url.toString() });
// Prisma 7: the pool belongs to the driver adapter (here, pg)
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "./generated/prisma";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
max: 10, // was connection_limit
connectionTimeoutMillis: 10_000, // was pool_timeout; pg's default 0 waits forever
});
export const prisma = new PrismaClient({ adapter });Serverless or long-running: different starting points
Copying serverless advice to a long-running server is a common mistake. connection_limit=1 on a Node server makes every request wait for the single connection, which turns a burst of traffic into a queue of P2024s.
| Where the app runs | Prisma’s starting point | Why |
|---|---|---|
| Serverless functions, no external pooler † | connection_limit=1, then tune | Each concurrent invocation is a separate process with its own pool. A traffic spike multiplies them. |
| Serverless functions behind a pooler (PgBouncer, Supavisor) † | The default pool, then tune. Add pgbouncer=true if the pooler runs in transaction mode | The pooler shares a few server connections among many clients. |
| One long-running server † | The default pool, or the default ÷ number of instances | One process, one pool, connections reused across requests. |
| Canner | Pool of 8, so production and a preview both fit in the 20, with room for migrations and psql | One long-running process per project, up to 20 connections per database. |
† Competitor details come from each vendor’s own published pages on the dates shown; prices and plans change, so check the vendor before you decide. Serverless functions, no external pooler (2026-10-29) · Serverless functions behind a pooler (PgBouncer, Supavisor) (2026-10-29) · One long-running server (2026-10-29)
Prisma on Canner
A Canner project runs one long-running process, and its database accepts up to 20 connections at once (background jobs docs). DATABASE_URL gives each connection its own Postgres session, so don’t add pgbouncer=true; that flag is for transaction-mode poolers.
- Set the pool explicitly. Prisma 6’s CPU-based default reflects the server your process lands on, not your plan. A fixed
connection_limit=8(ormax: 8on Prisma 7) behaves the same everywhere. - Keep headroom for the release command.
prisma migrate deployruns while the current version is still serving and opens its own connection (where migrations run). - Count previews. A preview deploy shares the project’s environment variables, so it is a second process with its own pool on the same database.
- If you outgrow 20, the answer on Canner is fewer, faster queries, not more connections. If your design needs many processes on one database at once, Canner is not the right fit today.
Questions
Should I set pool_timeout=0 to stop P2024?
Only for batch work where waiting is fine, such as a large import with many parallel queries. Prisma documents it for that case. On a web server it turns a clear error into requests that hang.
Does connection_limit=1 fix P2024?
On serverless functions without a pooler it is Prisma’s recommended start. On a long-running server it makes things worse: every query in the process shares one connection.
Why do I only get P2024 in development with Next.js?
Hot reload re-runs the module that creates PrismaClient, and each new client opens its own pool while the old ones linger. Store the client on globalThis outside production, as in the snippet above.
Does Prisma 7 still throw P2024?
With a driver adapter, the pool is the driver’s. With pg the default acquire timeout is 0, so queries wait instead of failing; set connectionTimeoutMillis and you get pg’s “timeout exceeded when trying to connect”.
What connection_limit should I use on Canner?
8 for one app. The database allows up to 20 connections, and a preview is a second process with its own pool; at 8 each, both fit with room for migrations and any psql session.
Run your Prisma app next to its database.
Every project gets a Postgres database in Montréal. Deploy from the terminal with the Canner CLI.