Overview

A connection pool lets application code borrow an open connection and return it, skipping the TCP, authentication, and TLS setup per query. PostgreSQL runs one backend process per connection, so a pool or external pooler is what keeps total connections under max_connections. Add a pooler before scaling out app instances or moving to serverless, since every new process multiplies open connections.

Rules

  • Size max per process from max_connections divided by the number of app instances, leaving headroom for migrations, admin sessions, and replicas. A queue inside the pool is cheaper than refused connections.
  • Put PgBouncer or your platform’s pooler between serverless functions and Postgres, because each short-lived instance opens its own pool.
  • PgBouncer transaction pooling breaks session state (SET, LISTEN, session advisory locks, WITH HOLD cursors). Protocol-level prepared statements work only when max_prepared_statements is above zero.
  • Prisma 7 delegates pooling to the driver adapter (with pg, the max option, default 10); connection_limit was the Prisma 6 engine setting.
  • Alert on pool wait time; it rises before errors do. Long transactions that hold a connection while waiting on locks drain the pool (deadlock).