Part 1 · 2 chapters · ~12 min

Process Architecture

The postmaster and a backend process per connection, background workers (checkpointer, bgwriter, WAL writer, autovacuum, WAL senders), shared memory and the double-buffering debate, startup and crash restart, and connection pooling as a requirement with PgBouncer's modes.

2

Postmaster, backends and background workers

code
-- what is running right now
SELECT pid, backend_type, state, wait_event_type, wait_event, now() - xact_start AS xact_age, left(query, 60)
FROM pg_stat_activity ORDER BY xact_age DESC NULLS LAST;

-- memory per backend that multiplies: work_mem is per sort/hash node, per query, per backend
SHOW work_mem;     -- 4MB default; 200 connections × 3 sorts × 64MB = 38 GB worst case

shared_buffers and the double-buffering debate: Postgres reads through the OS page cache, so a hot page can live both in shared_buffers and in the kernel cache. The usual guidance is shared_buffers at about 25% of RAM and effective_cache_size (a planner hint, not an allocation) at 50-75%, leaving the OS cache to do the rest. Postgres 18's asynchronous IO and ongoing direct IO work are steps away from relying on the kernel cache.

PROCESS ARCHITECTURE
a postmaster, one backend process per connection, and background workers around shared memory
connectforkclientsapps, psqlpostmasterlistens, forksbackend × None per connectionshared memorybuffers, locks, WAL bufferscheckpointerbgwriterWAL writerautovacuumWAL sender
swipe the figure sideways, or tap expand for full screen
1/5
postmaster
The postmaster is the supervisor. It listens on the port and, for each new connection, forks a backend process. It does not touch data itself.
one supervisor process that forks backendsit never runs queries itself
3

Connection pooling as a requirement

PgBouncer modeserver connection held forbreaksuse
sessionthe whole client sessionnothingonly limits connection churn; no multiplexing
transactionone transactionSET (use SET LOCAL), session advisory locks, LISTEN, WITH HOLD cursors, temp tables across transactionsthe standard for web apps
statementone statementmulti-statement transactionsrare; autocommit-only workloads
code
; pgbouncer.ini
[databases]
app = host=10.0.0.5 dbname=app
[pgbouncer]
pool_mode = transaction
max_client_conn = 5000          ; clients PgBouncer accepts
default_pool_size = 40          ; server connections per database/user pair
max_prepared_statements = 200   ; protocol-level prepared statements in transaction mode (1.21+)

Startup sequence, briefly: the postmaster reads configuration, allocates shared memory, starts the startup process to replay WAL if the last shutdown was not clean (reading pg_control), then starts background workers and accepts connections. Alternatives to PgBouncer: PgCat and Supavisor (multi-threaded poolers with sharding features), Odyssey, and cloud proxies such as RDS Proxy.