Chapter 02 · Cluster Architecture, Processes, Memory, Files, and Configuration
Postmaster, Backend Processes, Auxiliary Processes, and Connection Lifecycle
Trace a PostgreSQL client connection from the listening postmaster through authentication to its dedicated backend process, then observe session state, cancellation, disconnection, and the auxiliary processes that keep the instance healthy.
Learning outcomes
ServiceHub now has a repeatable PostgreSQL lab from Chapter 01. The next operational question is deceptively simple: what actually happens when an application opens a database connection? If you think of PostgreSQL as one monolithic process with “threads for users,” you will misread memory use, process listings, connection limits, cancellation behavior, and the reason connection pools matter.
PostgreSQL uses a process-oriented client/server model. A main server process—historically called the postmaster—listens for connection requests and arranges a dedicated backend process for each ordinary client session. The instance also runs auxiliary processes for tasks such as checkpoints, WAL writing, background writing, autovacuum coordination, logging, archiving, recovery, and other enabled features. The exact process set is version- and configuration-dependent, so production diagnosis begins with observation rather than memorizing a screenshot.
Distinguish the main server process, per-session backend processes, auxiliary processes, and optional/background workers.
Trace a connection from listener acceptance through authentication and backend session state to clean disconnect or cancellation.
Correlate pg_stat_activity.pid,
pg_backend_pid(), application names, and
operating-system processes without overclaiming what each
proves.
Explain why PostgreSQL connection scaling differs from
thread-pooled server architectures and why
max_connections is not a throughput knob.
Use safe cancellation/termination and timeout concepts without treating process killing as normal application flow.
Reuse the disposable Chapter 01 instance on port
55432 and the
servicehub_lab database. Prefer the
servicehub-lab-admin and
servicehub-lab-app service entries created
earlier. If your local package uses port 5432 instead, keep
your own verified port; do not change a working server merely
to match a screenshot.
1. The process-per-session mental model
The main PostgreSQL server process owns the listening sockets and supervises the instance. When a client connects, PostgreSQL creates a backend process dedicated to that session. The backend parses statements, plans and executes queries, owns session-local state, participates in transactions, and communicates with shared-memory structures and other server processes.
client / psql / driver | | TCP or Unix-domain socket v+---------------- main PostgreSQL server (postmaster) ----------------+| listens -> accepts connection -> startup/authentication handshake |+-------------------------------+-------------------------------------+ | v dedicated backend process for this client session | | | | | +--> local/session state | +---------> shared memory + locks +----------------> relation/WAL I/O via server mechanismsAuxiliary/background processes run beside backends:checkpointer, background writer, WAL writer, autovacuum launcher,logger when enabled, archiver when enabled, recovery/WAL receiver when applicable,plus feature-specific workers.
This diagram intentionally leaves out many details. It is useful because it puts responsibility in the right place: your application does not create a “database process” that owns all other sessions, and one backend is not the entire PostgreSQL server.
| Thing | Practical responsibility | Common mistake |
|---|---|---|
| Main server / postmaster | Owns instance startup, listening endpoints, child-process supervision, and propagation of events such as configuration reload. | Assuming its PID is the PID that executes every query. |
| Backend process | Acts on behalf of one connected session and holds that session’s state. | Assuming one backend serves the entire connection pool simultaneously. |
| Auxiliary process | Performs a particular instance-level background responsibility. | Assuming every named process is always present in every topology. |
| Background worker | Runs built-in or extension-supplied background work, including feature-specific tasks. | Calling every background worker an auxiliary process. |
2. Follow one ServiceHub session end to end
Open the application service and explicitly label the
connection. application_name is not security—it is
observability metadata—but it makes process/session correlation
much easier.
psql "service=servicehub-lab-app application_name=bda_ch02_l1_app"
Once connected, ask PostgreSQL for identifiers and context instead of guessing.
SELECT pg_backend_pid() AS my_backend_pid, current_database() AS database_name, current_user AS role_name, current_setting('application_name') AS application_name, inet_server_addr() AS server_address, inet_server_port() AS server_port;SELECT pid, usename, datname, application_name, client_addr, backend_start, xact_start, query_start, state, wait_event_type, wait_eventFROM pg_catalog.pg_stat_activityWHERE pid = pg_backend_pid();
The PID returned by pg_backend_pid() is the
operating-system process ID for this backend on a normal
PostgreSQL server. The row in pg_stat_activity adds
server-side session metadata. A state of
active means the backend is executing a query at
the moment the statistics snapshot is observed;
idle means it is waiting for the next client
command; idle in transaction is more concerning
because an open transaction remains while the client is doing
nothing.
A matching PID and application name prove that the current server knows about that backend session. They do not prove the client is using least privilege, that all other sessions are healthy, or that connection count is safe under peak load.
3. See the operating-system process without making the lab platform-specific
On Linux and many Unix-like systems, process listings will
normally show a main postgres process and child
processes whose process titles describe their roles. On Windows,
PostgreSQL still uses separate server processes even though
process creation details differ from Unix. Container runtimes
add another boundary: the PostgreSQL processes live inside the
container’s process namespace unless you inspect them from the
host with container-aware commands.
# Linux/macOS when PostgreSQL processes are visible on the hostps -ef | grep '[p]ostgres'# Docker / Podman-style container lab# Replace the container name with the one you actually use.docker top bda-postgres-18# Windows PowerShell: inspect postgres.exe processesGet-Process postgres -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime
Do not force these commands to match line-for-line. Package
managers, service wrappers, containers, localization, and
enabled features affect process titles. Use the database PID
from pg_backend_pid() as the correlation anchor.
4. What auxiliary processes are doing—and why the list changes
PostgreSQL 18’s glossary distinguishes auxiliary processes from
ordinary backends and background workers. Important examples
include the checkpointer, background writer, WAL writer,
autovacuum launcher, logger, startup process, WAL archiver, WAL
receiver, and WAL summarizer. Some only exist when a feature or
topology requires them. For example, a WAL receiver belongs to a
standby receiving WAL, and the logging collector only exists
when logging_collector is enabled.
| Process/function | Why it exists | When you should care |
|---|---|---|
| Checkpointer | Coordinates checkpoints so dirty pages and WAL recovery boundaries progress safely. | Checkpoint frequency, write spikes, crash-recovery expectations. |
| Background writer | Writes selected dirty shared buffers in the background. | Write behavior and buffer reuse; not a substitute for understanding checkpoints. |
| WAL writer | Flushes WAL buffers periodically. | Commit/WAL behavior and I/O diagnosis. |
| Autovacuum launcher | Schedules autovacuum worker activity. | Dead tuple cleanup, statistics, transaction-ID safety. |
| Logger |
Collects stderr into log files when
logging_collector is enabled.
|
Structured logging and log-file location. |
| Startup / WAL receiver | Recovery and standby responsibilities. | Physical replication and recovery chapters. |
Later chapters revisit each mechanism. The goal here is to recognize that these are instance-level actors, while your ordinary ServiceHub query runs in its own backend.
5. Connection lifecycle: authentication is only one stage
A simplified lifecycle is: network/socket connection → startup packet → optional transport negotiation → authentication and authorization to connect → database/session startup → commands and transactions → cancellation/disconnect → backend cleanup. A connection can fail at several layers, and the error message usually tells you which layer rejected it.
SELECT pid, now() - backend_start AS connection_age, now() - xact_start AS transaction_age, state, wait_event_type, wait_event, left(query, 100) AS query_sampleFROM pg_catalog.pg_stat_activityWHERE datname = 'servicehub_lab'ORDER BY backend_start;
xact_start is NULL when no transaction is active.
That is useful when diagnosing unexpectedly long transactions:
connection age and transaction age are not the same thing.
6. Cancellation is not termination
PostgreSQL exposes two different administrative concepts.
pg_cancel_backend(pid) requests cancellation of the
current query while keeping the session alive.
pg_terminate_backend(pid) ends the session itself.
Both require appropriate privilege for other sessions and should
be driven by evidence, not by “kill whatever is slow.”
For a safe demo, use two administrator sessions on the disposable lab. In session A, start a harmless long-running query:
SELECT pg_backend_pid() AS session_a_pid;SELECT pg_sleep(30);
In session B, locate the session by application name or PID and cancel it:
SELECT pid, application_name, state, wait_event_type, wait_event, queryFROM pg_catalog.pg_stat_activityWHERE datname = 'servicehub_lab' AND query LIKE '%pg_sleep%';-- Substitute the verified PID from the previous result.SELECT pg_cancel_backend(12345);
Session A should receive an error similar to
canceling statement due to user request, but the
session remains usable. Run SELECT 1; there to
prove the backend still accepts commands. This is different from
terminating the backend.
7. Deliberately wrong approach: “just raise max_connections”
A common response to connection exhaustion is to treat
max_connections as a throughput dial: if 100
sessions are insufficient, set 1,000 or 5,000. That is unsafe
reasoning. PostgreSQL’s process-per-session model means more
connections imply more backend processes and more potential
private/session allocations. At the same time, each query can
allocate memory for sorts, hashes, and other operations. A high
connection limit without a workload/memory budget can turn a
connection incident into memory pressure and latency collapse.
SHOW max_connections;SHOW superuser_reserved_connections;SELECT state, count(*) AS sessionsFROM pg_catalog.pg_stat_activityGROUP BY stateORDER BY sessions DESC;SELECT count(*) FILTER (WHERE datname = 'servicehub_lab') AS servicehub_sessions, count(*) AS all_sessionsFROM pg_catalog.pg_stat_activity;
The repair is not automatically “lower max_connections” either. First determine peak concurrent work, pool behavior, transaction duration, query latency, memory budget, and whether idle application connections can be multiplexed through a connection pooler. Poolers are important but are third-party/external operational components; they are not a required dependency for this course lab.
8. Hands-on lab: correlate three ServiceHub sessions
-
Open three terminals using the application service and give
each a distinct
application_name:bda_worker_a,bda_worker_b, andbda_report. -
In each terminal run
SELECT pg_backend_pid();and record the PID. -
From an administrator session query
pg_stat_activityfor those application names. -
Start
SELECT pg_sleep(20);in one worker and observe itsstateand wait event. -
Cancel the sleep from the administrator session, then prove
the worker session still executes
SELECT 1;. -
Disconnect one terminal with
\qand verify its row disappears frompg_stat_activity.
SELECT pid, usename, datname, application_name, state, wait_event_type, wait_event, backend_start, xact_startFROM pg_catalog.pg_stat_activityWHERE application_name IN ('bda_worker_a','bda_worker_b','bda_report')ORDER BY application_name;
Check your understanding
- What is the difference between the postmaster/main server process and an ordinary backend process?
- Why can two psql sessions connected to the same database have different PIDs?
-
What does
idle in transactiontell you that connection age alone does not? -
When is
pg_cancel_backendpreferable topg_terminate_backend? -
Why is raising
max_connectionswithout a memory/workload model risky?
Review the answers
The main server supervises the instance and accepts new
connections; each ordinary client gets a dedicated backend
process. Separate sessions therefore have separate backend
PIDs. idle in transaction means a transaction
remains open while the client is inactive, which can
retain locks/snapshots and create operational problems.
Cancellation stops the current statement while preserving
the session, whereas termination ends the session.
Finally, more allowed connections can mean more processes
and many more concurrent private/per-operation
allocations, so connection capacity must be budgeted with
workload and memory.
9. Production judgment and next bridge
Use process/session evidence when diagnosing connection storms, long transactions, blocked work, runaway queries, or unexplained memory pressure. Do not build monitoring around fragile parsing of operating-system process titles alone; correlate PostgreSQL views, application names, PIDs, role/database identity, and host-level metrics. In production, connection pools should have explicit limits and timeouts, but their exact size must come from measured workload behavior.
Now that you can identify the actors in a running instance, Lesson 2 maps where those processes obtain durable configuration and where PostgreSQL stores cluster-managed files.