Lab 11: PgBouncer Advanced

Time: 45 minutes | Level: Advanced | DB: PostgreSQL 15 + PgBouncer

Overview

PostgreSQL creates a new OS process per connection — expensive at 500+ connections. PgBouncer maintains a small pool of actual database connections and multiplexes thousands of client connections through them, dramatically reducing memory and CPU overhead.


Step 1: Launch PostgreSQL Backend

docker network create pgbouncer-net

docker run -d \
  --name pg-backend \
  --network pgbouncer-net \
  --hostname pg-backend \
  -e POSTGRES_PASSWORD=rootpass \
  -e POSTGRES_DB=appdb \
  postgres:15 \
  -c max_connections=100 \
  -c log_connections=on \
  -c log_disconnections=on

sleep 12

# Create application user and schema
docker exec pg-backend psql -U postgres appdb <<'EOF'
CREATE USER appuser WITH PASSWORD 'apppass';
GRANT ALL ON DATABASE appdb TO appuser;

\c appdb appuser

CREATE TABLE sessions (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id INT,
  data JSONB,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

INSERT INTO sessions (user_id, data)
SELECT gs, ('{"active": true, "score": ' || (random()*100)::int || '}')::jsonb
FROM generate_series(1, 1000) gs;

SELECT COUNT(*) FROM sessions;
EOF

📸 Verified Output:


Step 2: Install and Configure PgBouncer

📸 Verified Output:


Step 3: Connect Through PgBouncer

📸 Verified Output:


Step 4: Pool Mode Comparison

📸 Verified Output:


Step 5: SHOW STATS and SHOW POOLS

📸 Verified Output:

💡 cl_active = active client connections; sv_idle = idle server connections ready for reuse. The key metric: many clients (cl_) can share few servers (sv_).


Step 6: Simulate Connection Pool Pressure

📸 Verified Output:

💡 50 clients → only 5 actual PostgreSQL connections! This is the core value of connection pooling.


Step 7: PAUSE and RESUME (Rolling Maintenance)

📸 Verified Output:


Step 8: Capstone — Dynamic Pool Sizing

📸 Verified Output:


Summary

Pool Mode
Connection Released
Supports
Best For

session

At client disconnect

Everything

Apps using SET, LISTEN/NOTIFY

transaction

At COMMIT/ROLLBACK

Most features

Web APIs, stateless backends

statement

After each statement

Read-only queries

Simple SELECT-only apps

Command
Purpose

SHOW POOLS

Active connections per pool

SHOW STATS

Query/transaction throughput

SHOW CLIENTS

Active client connections

SHOW SERVERS

Actual PostgreSQL connections

PAUSE dbname

Block new queries (for maintenance)

RESUME dbname

Unblock after pause

RELOAD

Reload config without restart

SET key=value

Dynamic config change

Key Takeaways

  • transaction pool mode is the sweet spot — efficient and compatible with most applications

  • 50 clients → 5 server connections is realistic — PgBouncer multiplexes aggressively

  • PostgreSQL max_connections should be low (100-200); PgBouncer handles the rest

  • PAUSE + RESUME enables zero-connection-error maintenance windows

  • Always test pool mode compatibility — SET search_path, LISTEN, and advisory locks require session mode

Last updated