From 0071b6182e83585eae708bb108b29f4a98f33879 Mon Sep 17 00:00:00 2001 From: valentinpanizza Date: Fri, 18 Sep 2026 14:00:15 -0300 Subject: [PATCH] fix(db): cap the pg connection pool, configurable per environment PrismaPg was constructed with just the connection string, so pg.Pool fell back to its default of 10 connections per process. On Vercel each warm serverless instance builds its own pool, so two instances already exceeded the 15 connections of Supabase's free session pooler. The failure surfaced as Prisma's "Can't reach database server", which reads like the database being down rather than its pool being full. Pass a PoolConfig instead: max comes from DB_POOL_MAX (default 3) so the serverless app and the long-lived worker can be tuned separately, and idleTimeoutMillis releases idle connections instead of holding them. --- lib/db/client.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/db/client.ts b/lib/db/client.ts index 17056a24f..86a40e231 100644 --- a/lib/db/client.ts +++ b/lib/db/client.ts @@ -11,8 +11,19 @@ function createPrismaClient() { throw new Error("DATABASE_URL environment variable is required"); } + // Without an explicit cap, pg.Pool opens up to 10 connections per process and + // the adapter was only given the connection string. On serverless every warm + // instance builds its own pool, so two of them already exceeded the 15 + // connections of Supabase's free session pooler — surfacing as Prisma's + // "Can't reach database server", which reads like an outage rather than an + // exhausted pool. The cap is per-environment: small on Vercel, a bit higher + // on the worker, which is a single long-lived process. return new PrismaClient({ - adapter: new PrismaPg(databaseUrl), + adapter: new PrismaPg({ + connectionString: databaseUrl, + max: Number(process.env.DB_POOL_MAX ?? 3), + idleTimeoutMillis: 10_000, + }), }); }