Connection Pooling Mistakes
The pool-sizing math everyone gets wrong the first time.
The Problem
Connection pools protect databases, but oversizing them can make performance worse. Too many active connections create context switching, lock contention, and memory pressure inside Postgres.
Why It Matters
Connection pool settings are multiplied by replicas. A harmless-looking pool size on one pod can become a production outage after autoscaling. Pooling is capacity control, not just a performance optimization.
PgBouncer, HikariCP, Prisma, node-postgres, and most backend frameworks expose pool settings. The defaults are not always right for your database size and deployment topology.
Project Example
If 20 API pods each use a pool of 50 connections, Postgres may see 1,000 possible connections before workers, migrations, and admin tools are counted. Most apps need smaller per-pod pools plus PgBouncer or careful autoscaling limits.
Implementation Example
database max connections: 300
reserved for admin/migrations: 30
reserved for workers: 70
available for API: 200
API replicas: 20
pool per API replica: 10
This is simple math, but many incidents happen because nobody writes it down.
Implementation Checklist
- Calculate total connections across all replicas.
- Set pool size from database capacity, not pod count.
- Track pool wait time and query duration separately.
- Use transaction pooling for short web requests when appropriate.
- Reserve connections for migrations and emergency access.
- Keep worker pools separate from request pools.
- Alert on pool exhaustion before requests time out.
- Review pool settings when autoscaling limits change.
Production Notes
If pool wait time is high but database CPU is low, you may need more connections. If database CPU, lock waits, or I/O are high, increasing the pool often makes the problem worse.
Common Mistakes
- Increasing pool size when queries are slow.
- Letting autoscaling multiply database connections.
- Sharing one pool between user requests and background jobs.
- Ignoring idle-in-transaction sessions.
- Forgetting serverless functions can create many short-lived connections.
How To Validate
Load test with the same replica count and pool settings used in production. Watch database CPU, active connections, idle connections, pool wait time, query latency, and lock waits together. A healthy pool should keep request wait time low without allowing the application to flood the database.
Summary
Good pooling is capacity control. Keep pools small, observable, and aligned with what the database can actually execute.
The weekly engineering digest
Production-grade engineering writing in your inbox. No spam, unsubscribe anytime.