Why this matters
Opening a TCP connection takes 1 round-trip. Adding TLS adds another. Adding Postgres handshake adds 2-3 more. Each connection: ~5-10ms of pure overhead before any query runs. If your app opens a new connection per request, that overhead kills you. Worse, every connection consumes ~10MB on the Postgres server — 1000 idle connections = 10GB of wasted RAM, and Postgres dies somewhere around 500-1000 connections regardless.
Connection pooling reuses a small set of long-lived connections for many requests. Saves the handshake overhead AND keeps the database alive. The most common production performance bug is not having one — or having one configured wrong.