From 74619bdaa9692f56d7fbc12a28f5985dc6150a12 Mon Sep 17 00:00:00 2001 From: pandoli365 Date: Wed, 8 Apr 2026 15:10:58 +0900 Subject: [PATCH] fix(db): tune pg pool keepalive and size Enable TCP keepalive, raise pool max to 100, and warm up a baseline of 20 connections at startup to reduce intermittent disconnects and cold-start latency. Made-with: Cursor --- src/database/index.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/database/index.ts b/src/database/index.ts index 5c850bc..df45375 100644 --- a/src/database/index.ts +++ b/src/database/index.ts @@ -42,6 +42,11 @@ const pool = new Pool({ connectionString: pgConnectionString, // Fail fast when DB is temporarily unreachable; connectDB will retry. connectionTimeoutMillis: 5_000, + // Pool sizing. `pg` doesn't support a true "min" size, so we warm up below. + max: 100, + // Help prevent intermediate network devices from dropping idle connections. + keepAlive: true, + keepAliveInitialDelayMillis: 10_000, // pg(Pool) doesn't understand Prisma's `?schema=...` param. // Force PostgreSQL search_path so both Prisma adapter and raw queries // operate on the intended schema (e.g. kord_live). @@ -56,6 +61,11 @@ export const prisma = new PrismaClient({ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); +const warmupPool = async (count: number) => { + const clients = await Promise.all(Array.from({ length: count }, () => pool.connect())); + for (const c of clients) c.release(); +}; + export const connectDB = async () => { const maxAttempts = 6; for (let attempt = 1; attempt <= maxAttempts; attempt++) { @@ -66,6 +76,9 @@ export const connectDB = async () => { const { rows } = await client.query('SHOW search_path;'); client.release(); + // Keep a baseline of connections ready (pg has no built-in min pool size). + await warmupPool(20); + let hostPort = 'unknown'; try { const u = new URL((process.env.DATABASE_URL || '').trim().replace(/^['"]|['"]$/g, ''));