Skip to content
$EngineeringAtlas

Connection Pooling Mistakes

The pool-sizing math everyone gets wrong the first time.

Amit Kumar Singh2 min read

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.

Amit Kumar Singh

// written by

Amit Kumar Singh

Software engineer writing about backend systems, cloud, and the realities of running code in production.

$ subscribe --weekly

The weekly engineering digest

Production-grade engineering writing in your inbox. No spam, unsubscribe anytime.

## related