Postgres Architecture
PostgreSQL is a multi-process server: a supervising postmaster forks backend processes per client connection while background workers maintain durability and cache hygiene. Understanding this split explains connection limits, memory sizing, and why restarts vs reloads differ.
Recipe
-- See live backends and what they run
SELECT pid, usename, application_name, state, wait_event_type, query
FROM pg_stat_activity
WHERE backend_type = 'client backend'
ORDER BY state, pid;# Reload config without dropping connections (many GUCs)
pg_ctl reload -D /var/lib/postgresql/18/main
# Full restart recycles postmaster and all children
pg_ctl restart -D /var/lib/postgresql/18/mainWhen to reach for this: You need to reason about connections, memory, checkpoints, or why a setting requires a restart.
Working Example
-- WAL generation rate hint (bytes per checkpoint cycle)
SELECT checkpoints_timed, checkpoints_req,
wal_bytes, buffers_checkpoint
FROM pg_stat_bgwriter;
-- Shared buffer hit ratio (database level)
SELECT sum(blks_hit)::float / nullif(sum(blks_hit) + sum(blks_read), 0) AS cache_hit_ratio
FROM pg_stat_database;What this demonstrates:
pg_stat_activityseparates client backends from background workerspg_stat_bgwriterexposes checkpoint and WAL volume- Buffer hit ratio approximates how often reads come from shared_buffers vs disk
- Reload vs restart is an operational distinction tied to postmaster lifecycle
Deep Dive
Process Model
- Postmaster listens on the port and forks a new backend per TCP connection (unless pooling).
- Background writer dirty-page flusher; checkpointer ends WAL segments and advances redo points.
- WAL writer groups WAL buffer fsyncs; autovacuum launcher schedules table vacuum/analyze workers.
- Stats collector and logical replication workers appear as additional background types.
Memory Layout
- shared_buffers holds cached data pages shared by all backends.
- Each backend has work_mem (per sort/hash node) and maintenance_work_mem (VACUUM, CREATE INDEX).
- effective_cache_size is a planner hint about OS page cache, not allocated RAM.
Durability Path
- Backend modifies shared buffer page and inserts WAL record.
- WAL is flushed to disk (commit depends on synchronous_commit).
- Checkpoint writes dirty pages; crash recovery replays WAL from last checkpoint.
Gotchas
- One backend per connection - Without PgBouncer, 500 app threads can mean 500 Postgres processes.. Fix: Pool at the app or PgBouncer; right-size max_connections.
- work_mem multiplies - Ten parallel sorts in one query can use 10x work_mem.. Fix: Cap work_mem; watch EXPLAIN for Sort/Hash nodes.
- Reload does not apply everything - shared_buffers changes need restart.. Fix: Check pg_settings.context before assuming reload works.
- Long idle in transaction - Open transactions block vacuum and retain row versions.. Fix: Set idle_in_transaction_session_timeout.
- Autovacuum is not optional - Updates/deletes leave dead tuples until vacuum runs.. Fix: Monitor pg_stat_user_tables.n_dead_tup.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Connection pooler (PgBouncer) | Many short-lived app connections | You need prepared statements pinned to one backend in transaction mode |
| Managed Postgres (RDS, Cloud SQL) | Ops team wants patching and backups handled | You need custom extensions or kernel tuning |
| Read replicas | Read-heavy reporting off primary | Synchronous replication adds commit latency |
FAQs
What is the difference between reload and restart?
Reload re-reads postgresql.conf for many parameters. Restart recycles all processes and is required for memory-related GUCs.
How many connections can Postgres handle?
Depends on RAM and workload. Hundreds of idle connections are cheap; hundreds of active queries are not. Pool aggressively.
Where is data stored on disk?
The data directory (PGDATA) holds heap files, WAL, and catalog. Use tablespaces only when you need separate storage paths.
Does PostgreSQL use threads?
No for backends. Parallel query workers are separate processes forked for a single statement.
What happens on crash?
On startup, Postgres replays WAL from the last checkpoint, then accepts connections.
Related
- PostgreSQL Basics - cluster, schema, and table tour
- Installation Basics - packages and data directory layout
- Transactions Basics - MVCC and WAL from the session view
- Connection Pooling Basics - reducing backend count
Stack versions: This page was written for PostgreSQL 18.4 (stable 18, maintenance 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, and PostGIS 3.5+.