Why pooling matters
PostgreSQL handles each connection as a separate OS process. 100 connections uses ~80MB just for overhead.
PgBouncer multiplexes many application connections onto a small pool of real database connections.
Setup
apt install pgbouncerConfigure /etc/pgbouncer/pgbouncer.ini with pool_mode = transaction and listen_port = 6432. Your app connects to 6432; PgBouncer talks to Postgres on 5432.