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
This commit is contained in:
김판돌 2026-04-08 15:10:58 +09:00
parent a69828e477
commit 74619bdaa9
1 changed files with 13 additions and 0 deletions

View File

@ -42,6 +42,11 @@ const pool = new Pool({
connectionString: pgConnectionString, connectionString: pgConnectionString,
// Fail fast when DB is temporarily unreachable; connectDB will retry. // Fail fast when DB is temporarily unreachable; connectDB will retry.
connectionTimeoutMillis: 5_000, 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. // pg(Pool) doesn't understand Prisma's `?schema=...` param.
// Force PostgreSQL search_path so both Prisma adapter and raw queries // Force PostgreSQL search_path so both Prisma adapter and raw queries
// operate on the intended schema (e.g. kord_live). // operate on the intended schema (e.g. kord_live).
@ -56,6 +61,11 @@ export const prisma = new PrismaClient({
const sleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms)); const sleep = (ms: number) => new Promise<void>(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 () => { export const connectDB = async () => {
const maxAttempts = 6; const maxAttempts = 6;
for (let attempt = 1; attempt <= maxAttempts; attempt++) { for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@ -66,6 +76,9 @@ export const connectDB = async () => {
const { rows } = await client.query('SHOW search_path;'); const { rows } = await client.query('SHOW search_path;');
client.release(); client.release();
// Keep a baseline of connections ready (pg has no built-in min pool size).
await warmupPool(20);
let hostPort = 'unknown'; let hostPort = 'unknown';
try { try {
const u = new URL((process.env.DATABASE_URL || '').trim().replace(/^['"]|['"]$/g, '')); const u = new URL((process.env.DATABASE_URL || '').trim().replace(/^['"]|['"]$/g, ''));