OUT-3631 | Error: Failed query: select "settings"."id", "settings"."workspace_id", "settings"."segment_id", "settings"."subheading", "settings"."content", "settings"."background_color", "settings"."banner_image_id", "settings"."banner_position_x", "settings"."banner_posi... - #197
OUT-3631 | Error: Failed query: select "settings"."id", "settings"."workspace_id", "settings"."segment_id", "settings"."subheading", "settings"."content", "settings"."background_color", "settings"."banner_image_id", "settings"."banner_position_x", "settings"."banner_posi...#197arpandhakal wants to merge 1 commit into
Conversation
Sets idle_timeout, max_lifetime, and connect_timeout on the postgres client so cached sockets to the Supabase transaction pooler (port 6543) are closed client-side before the pooler evicts them, preventing the transient CONNECTION_CLOSED write errors on the first query after an idle period on warm Vercel runtimes. Also drops debug: true so we stop logging every query in production. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR fixes a Confidence Score: 5/5Safe to merge — driver-level config only, no query semantics or schema changes. The change is minimal and well-targeted: three standard postgres.js timeout options plus removal of a debug flag. Values are correct (max_lifetime: 60*30 = 1800 s = 30 min matches the PR description). No P0 or P1 issues found. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Vercel as Vercel Lambda (warm)
participant PGClient as postgres.js client (singleton)
participant Pooler as Supabase Pooler port 6543
Note over PGClient: idle_timeout=20s, max_lifetime=1800s
Vercel->>PGClient: query (first request after idle)
alt Before fix — stale socket
PGClient->>Pooler: write on cached TCP socket
Pooler-->>PGClient: CONNECTION_CLOSED (pooler evicted)
PGClient-->>Vercel: Failed query error (Sentry OUT-3631)
else After fix — client recycles first
Note over PGClient: idle_timeout fires after 20s idle, closes socket proactively
PGClient->>Pooler: new TCP connect (connect_timeout=10s)
Pooler-->>PGClient: connection established
PGClient->>Pooler: query
Pooler-->>PGClient: result
PGClient-->>Vercel: success
end
Reviews (1): Last reviewed commit: "fix(OUT-3631): recycle idle postgres soc..." | Re-trigger Greptile |
priosshrsth
left a comment
There was a problem hiding this comment.
@arpandhakal I have approved this one if we want to merge it.
Changes
postgresclient insrc/db/db.tswithidle_timeout: 20,max_lifetime: 30m, andconnect_timeout: 10so cached TCP sockets to the Supabase transaction pooler (port 6543) are recycled client-side before the pooler evicts them.debug: trueso the driver stops logging every query in production.Context
Sentry issue OUT-3631 surfaced a
Failed querywrapping an innerwrite CONNECTION_CLOSED aws-1-us-east-1.pooler.supabase.com:6543onGET /duringsettingsService.getForWorkspace().The query itself is fine — the real failure is that the pooler had already closed the TCP socket that
postgreshad cached on a warm Vercel runtime. The next write onto that stale socket blew up before bytes left the process. On Supavisor/PgBouncer + Vercel this is a well-known pattern: the client never proactively recycles idle sockets, so the first request after an idle period on a reused lambda racing the pooler's own eviction timeout gets aCONNECTION_CLOSED. That matches the observed frequency (1 occurrence in the last 90 days).The fix sets client-side lifetimes shorter than the pooler's, so the client always wins the race and reconnects cleanly.
Testing Criteria
settings-actionsquery path that crashed).postgresdebug query spam after deploy.CONNECTION_CLOSEDerrors over the next 90 days.Notes
idle_timeoutandmax_lifetimeare standardpostgres.jsoptions recommended for Supavisor/PgBouncer setups.Impact & Surface Area of Change
src/db/db.ts. Risk is minimal because the only behavioral changes are (a) idle sockets close sooner and (b) queries are no longer logged in production. Query semantics are unchanged.🤖 Generated with Claude Code