From eaa01d25f98f3cdb005ccab7e31b29550dce2788 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 11 May 2026 15:56:25 +0200 Subject: [PATCH] perf(db): bump postgres pool to 60 in development to prevent hub-hang under fanout load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default max=20 was saturating during normal admin clickthrough — the clients list page does aggregate-per-client queries (yachts, memberships, interests, contacts) that fan out 5-6 connections per row, plus dashboard analytics, plus React Query refetch-on-focus. With 20 slots, the server appeared to hang for 30s (statement_timeout) until queries released their slots. Production keeps the conservative max=20 since multi-replica deployments share the postgres max_connections budget. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/db/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts index 223cf2b5..21e2efaa 100644 --- a/src/lib/db/index.ts +++ b/src/lib/db/index.ts @@ -18,8 +18,14 @@ const connectionString = process.env.DATABASE_URL!; // `max_lifetime` recycles connections every 30 minutes so any // per-connection state drift (prepared statements, GUCs) doesn't // accumulate forever. +// Larger pool in development because Next dev fans out (HMR refetches, +// multi-widget dashboards, React Query refetch-on-focus) and a single +// admin clicking around can saturate 20 slots. Production stays at the +// conservative 20 so we don't hammer postgres in a multi-replica deploy. +const POOL_MAX = process.env.NODE_ENV === 'development' ? 60 : 20; + const queryClient = postgres(connectionString, { - max: 20, + max: POOL_MAX, idle_timeout: 20, connect_timeout: 10, max_lifetime: 60 * 30,