PostgreSQLXVI · Observability, Logging and AlertingObservability
Correlating PostgreSQL evidence with the operating system
What you'll learn
- Join a backend to its operating system process and back
- Choose the OS instrument that matches the wait event class
- Avoid the memory-accounting mistakes shared memory causes
- Sample two instruments closely enough to compare them
Prerequisites
Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27
PostgreSQL knows what it is waiting for. The operating system knows what the machine is doing. Neither is sufficient, and joining them is one column.
The join
$ SELECT pid, state, wait_event_type, wait_event, left(query,32) AS query
FROM pg_stat_activity WHERE backend_type='client backend' AND state='active' LIMIT 4; pid | state | wait_event_type | wait_event | query
-----+--------+-----------------+---------------+----------------------------------
880 | active | LWLock | WALWrite | END;
881 | active | Lock | transactionid | UPDATE pgbench_branches SET bbal
882 | active | IO | WalSync | END;
883 | active | LWLock | LockManager | UPDATE pgbench_branches SET bbal$ ps -o pid,stat,time,rss,vsz,comm -p 880,881,882,883 PID STAT TIME RSS VSZ COMMAND
880 Ss 00:00:00 70800 229688 postgres
881 Ds 00:00:00 66188 229708 postgres
882 Ss 00:00:00 69132 229708 postgres
883 Ss 00:00:00 71720 229688 postgres$ grep -E '^(VmRSS|Threads|voluntary_ctxt|nonvoluntary_ctxt)' /proc/880/statusVmRSS: 70800 kB
Threads: 1
voluntary_ctxt_switches: 6657
nonvoluntary_ctxt_switches: 22Threads: 1 — one thread per backend, the process model from Part I,
seen from the other side.
Choosing the OS instrument from the wait event
The wait event class tells you which OS tool will have something to say:
| Wait event class | Look at | With |
|---|---|---|
IO/DataFileRead | Disk read latency and queue depth | iostat -x 1, biolatency |
IO/WalSync | fsync latency | iostat -x 1, pg_test_fsync |
LWLock | CPU and context switches | top, vmstat 1, /proc/PID/status |
Lock | Nothing in the OS. Application contention | Part IX |
Client | Network and the application | ss -tn, application logs |
NULL (running) | CPU saturation | top, mpstat, perf |
That mapping saves the most common wasted hour in database
troubleshooting: reaching for iostat when the wait events say Lock.
The disk is not the problem, has never been the problem, and will look
fine no matter how long you stare at it.
The system-level numbers that matter
vmstat 1 5 # r, b, si, so, us, sy, wa
iostat -x 1 5 # r_await, w_await, %util, aqu-sz
free -m # and the caveat below
ss -s # connection counts and states
df -h /var/lib/postgresql /var/lib/postgresql/*/main/pg_wal
The ones worth knowing by heart:
vmstatsi/sonon-zero — swapping. Lesson XI-06.vmstatb— processes blocked on I/O.vmstatwa— CPU time waiting on I/O.iostatr_await/w_await— per-request latency. The number that corresponds toIO/*wait events.dfonpg_walseparately — lesson XII-03’s outage.
What to take from this
pg_stat_activity.pidis the OS pid. That is the whole join.- Two instruments sampled microseconds apart need not agree. Sample close together and profile rather than snapshot.
- Let the wait event class choose the OS tool.
Lockmeans the OS has nothing to say. - Know
vmstatsi/so/b/waandiostatr_await/w_await. - Never sum RSS across backends —
shared_buffersis counted in each. Measured: 728 MB of RSS over 128 MB of buffers. - Inside a container,
freereports the host. Read the cgroup files. - Capture before you fix. The best evidence exists only while the problem does.
Cross-course references
- Linux for Production Sysadmins — Part XXXVIII (Linux performance fundamentals), Part XL (Memory Performance) and Part XLI (Storage Performance) cover the host-side instruments this lesson pairs with the database’s own.
- Observability for Production Sysadmins — Part LI (Correlating metrics, logs, and traces) and Part LVI (Linux observability) cover putting both on one timeline, which is what makes the correlation an argument rather than a coincidence.
- Docker & Containers — Part XV (Resource controls) covers why host figures and container figures disagree, and which one the OOM killer uses.
Quiz
Knowledge check · 6 questions
Q1. A monitoring system sums RSS across all PostgreSQL backends and reports 40 GB used on a host with 32 GB of RAM. What is wrong?
Q2. Wait-event sampling shows the backends are overwhelmingly on Lock waits. Which operating system tool will help?
Q3. Inside a container, free -m reports 47 GB available on a cluster limited to 2 GB. Why, and what should be read instead?
Q4. Which evidence exists only while an incident is happening? Select all that apply.
Q5. PostgreSQL reporting a Lock wait while ps shows the same process in state D is evidence that the two views are inconsistent.
Q6. Why should capturing evidence precede fixing during a database incident, and what should be captured?
Passing score: 75%. Answers are checked in this browser.