PostgreSQL Connection Pooling: Direct, Session, or Transaction?

Ghazi · July 31, 2026

A PostgreSQL connection is a server process with authentication and session state. Poolers reduce the number of server connections, but the pooling mode determines which state survives between statements and transactions.

Use direct connections or session pooling for interactive database clients. Use transaction pooling for short application transactions only after checking prepared statements, temporary tables, LISTEN, advisory locks, and session-level settings.

Identify the session you actually reached

select
  pg_backend_pid() as backend_pid,
  current_database() as database_name,
  current_user,
  inet_server_addr() as server_address,
  inet_server_port() as server_port;

show application_name;
show search_path;

Run this in separate transactions. A changing backend PID can be expected with transaction pooling, while a stable direct or session-pooled connection keeps one backend for the client session.

Direct connections preserve the full session

A direct client connects to a PostgreSQL backend and keeps it until disconnect. Temporary tables, prepared statements, SET values, LISTEN registrations, advisory locks, and transaction state all belong to that session.

The cost is one backend per active connection. That is reasonable for a handful of developer tools, but a bursty application can exhaust max_connections or spend too much memory on idle sessions.

Session pooling reuses connections between clients

A session pool gives one server connection to a client for the duration of its client session, then returns it to the pool. Most session behavior works normally while the client is attached.

This mode fits tools that expect a stable session but still need a pool in front of the database. Capacity savings are smaller when many client sessions remain open and idle.

Transaction pooling trades state for density

A transaction pool returns the server connection after each transaction. The next transaction may use another backend. That lets many clients share fewer PostgreSQL processes, which is useful for serverless functions and short web requests.

Session-scoped behavior needs special care. Some poolers support protocol-level prepared statements, but SQL PREPARE, temporary objects, SET without SET LOCAL, LISTEN, and session advisory locks do not become transaction-scoped simply because a pooler is present.

Read the provider URL instead of guessing

Supabase commonly exposes a direct endpoint, a session pooler on port 5432, and a transaction pooler on port 6543. Neon distinguishes pooled hostnames with -pooler. Provider behavior and connection strings can change, so copy the current URL from the project dashboard.

The Supabase guide and Neon guide show the connection fields for an interactive Mac client.

Match the pool to the workload

Inventory session features before changing an existing application. Run integration tests through the exact pool endpoint, with concurrent traffic and connection recycling. A health check that only runs SELECT 1 will not reveal broken session assumptions.

For PostgresGUI, psql, migrations, and administrative work, choose a stable direct or session connection. For high-concurrency stateless request handlers, transaction pooling is often the better starting point.