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.

Intermediate95–115 minutesProcess model + connection lifecycle labCurrent patched PostgreSQL 18.xpsql + OS process inspectionLast reviewed: August 2026

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.

01

Distinguish the main server process, per-session backend processes, auxiliary processes, and optional/background workers.

02

Trace a connection from listener acceptance through authentication and backend session state to clean disconnect or cancellation.

03

Correlate pg_stat_activity.pid, pg_backend_pid(), application names, and operating-system processes without overclaiming what each proves.

04

Explain why PostgreSQL connection scaling differs from thread-pooled server architectures and why max_connections is not a throughput knob.

05

Use safe cancellation/termination and timeout concepts without treating process killing as normal application flow.

Lab continuity

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.

text · simplified connection and process model
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.

text · connect with a visible application name
psql "service=servicehub-lab-app application_name=bda_ch02_l1_app"

Once connected, ask PostgreSQL for identifiers and context instead of guessing.

sql · identify the backend and session
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.

What the evidence proves

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.

text · optional process observation by platform
# 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.

sql · observe connection age and state
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:

sql · session A: create a cancellable 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:

sql · session B: cancel only the current query
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.

sql · inspect connection capacity instead of guessing
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

  1. Open three terminals using the application service and give each a distinct application_name: bda_worker_a, bda_worker_b, and bda_report.
  2. In each terminal run SELECT pg_backend_pid(); and record the PID.
  3. From an administrator session query pg_stat_activity for those application names.
  4. Start SELECT pg_sleep(20); in one worker and observe its state and wait event.
  5. Cancel the sleep from the administrator session, then prove the worker session still executes SELECT 1;.
  6. Disconnect one terminal with \q and verify its row disappears from pg_stat_activity.
sql · administrator verification query
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

  1. What is the difference between the postmaster/main server process and an ordinary backend process?
  2. Why can two psql sessions connected to the same database have different PIDs?
  3. What does idle in transaction tell you that connection age alone does not?
  4. When is pg_cancel_backend preferable to pg_terminate_backend?
  5. Why is raising max_connections without 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.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.