fix(db): cap the pg connection pool, configurable per environment - #71
Open
valentinpanizza wants to merge 1 commit into
Open
valentinpanizza wants to merge 1 commit into
valentinpanizza wants to merge 1 commit into
Conversation
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.
|
@valentinpanizza is attempting to deploy a commit to the diwenne's projects Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What happens
On a Vercel + Supabase deployment, the app and the worker intermittently fail with
which reads like the database being down. It is not — the connection pool is full.
Connecting from anywhere else at that moment returns:
In my case it broke sign-in entirely (a magic-link request 500s), and the worker
logged "Can't reach database server" every few minutes for two days before I found
the real cause.
Root cause
lib/db/client.tsconstructs the adapter with the connection string alone:PrismaPgaccepts apg.PoolConfig, but given only a string it falls back topg.Pool's default of 10 connections per process, and Prisma's ownconnection_limitURL parameter does not apply to the driver adapter — it is aquery-engine setting, so adding it to
DATABASE_URLsilently changes nothing.On serverless that is per warm instance. Supabase's free session pooler allows 15
connections total, so two warm Vercel instances plus a long-running worker exhaust
it. Traffic does not need to be high: two instances is enough.
The fix
Pass a real
PoolConfig:DB_POOL_MAXis per-environment on purpose, because the two runtimes wantdifferent values: the serverless app wants 1 (many short-lived instances), while
the single long-lived worker can use 3. The default of 3 keeps existing
self-hosted deployments closer to sane than the current implicit 10.
idleTimeoutMillisreleases idle connections instead of holding them for the lifeof the instance, which is what let a handful of warm lambdas sit on the whole pool.
Verification
With
DB_POOL_MAX=1on Vercel and 3 on the worker, the same deployment went from apermanently exhausted pool (15/15, sign-in failing) to 4 of 15 at rest, and the
intermittent "Can't reach database server" errors stopped.
Nothing changes for anyone who does not set the variable beyond the pool being
bounded at 3 instead of an implicit 10.