Managing Database Connections

1. Configuring Connection Pool

ParamDetail
connection_limitDefault = num_cpus * 2 + 1
URL?connection_limit=20
Per-processEach client has own pool

2. Setting Connection Timeout

ParamDetail
connect_timeoutTCP handshake max (sec)
Default5 sec

3. Configuring Pool Timeout

ParamDetail
pool_timeoutWait for free conn (sec)
Default10 sec
ErrorP2024 on exhaustion

4. Managing Connection Lifecycle

PhaseAPI
OpenLazy; $connect() forces
Close$disconnect()
RestartCreate new client

5. Handling Connection Errors

CodeMeaning
P1001Can't reach DB
P1002Timed out
P1008Operations timed out
P2024Pool exhausted

6. Using Multiple Database Connections

PatternDetail
Multi-tenantOne client per tenant URL
Read/write splitSeparate clients
Cache poolLRU map keyed by URL hash

7. Implementing Connection Retry Logic

async function withRetry<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try { return await fn(); }
    catch (e: any) {
      if (!["P1001","P1008","P2024"].includes(e.code) || attempt === retries) throw e;
      await new Promise(r => setTimeout(r, 100 * 2 ** attempt));
    }
  }
  throw new Error("unreachable");
}
PatternDetail
Exponential backoff100ms, 200ms, 400ms ...
IdempotencyRetry only safe ops

8. Closing Connections

process.on("SIGTERM", async () => {
  await prisma.$disconnect();
  process.exit(0);
});
AspectDetail
GracefulDrain pool before exit
ServerlessUsually unnecessary (runtime kills)

9. Using Read Replicas

ApproachDetail
Multiple clientsOne per replica URL
Extension@prisma/extension-read-replicas
Routing$replica() returns read-only client

10. Monitoring Connection Health

MetricSource
Pool sizeprisma.$metrics.json()
Active queriesDB-side (pg_stat_activity)
ErrorsCapture P10xx codes