You query pg_stat_activity during a performance incident and see non-NULL wait_event_type and wait_event values — here is how to read them quickly.
Diagnose it
-- Current wait snapshot grouped by class:
SELECT wait_event_type,
wait_event,
count(*) AS backends,
count(*) FILTER (WHERE state = 'active') AS active_backends
FROM pg_stat_activity
WHERE wait_event_type IS NOT NULL
AND backend_type != 'autovacuum launcher'
GROUP BY wait_event_type, wait_event
ORDER BY backends DESC;
Why it happens
When a backend is waiting, PostgreSQL records the class (wait_event_type)
and specific event (wait_event). Key classes:
- Lock — waiting for a heavyweight lock on a relation, tuple, page, or transaction.
Investigate with pg_locks.
- LWLock — waiting for a lightweight lock protecting an internal shared-memory
structure. Usually transient; sustained LWLock waits suggest very high concurrency.
- IO — backend is waiting for a read or write to complete. Indicates I/O
pressure or missing pages in shared_buffers.
- IPC — inter-process communication (e.g., waiting for a parallel worker
or background process to respond).
- Client — waiting to send data to the client (
ClientWrite) or
receive a command (ClientRead). Usually harmless; high ClientRead
counts suggest a slow client or network.
- Timeout — backend is sleeping intentionally (e.g., autovacuum worker
between pages — see VacuumDelay).
How to fix it
No single fix — the wait event points you to the right tool: