Wait event metrics
Active session history and wait event metrics from pg_stat_activity.
Data source
Wait event data is collected from pg_stat_activity:
select
pid,
state,
wait_event_type,
wait_event,
query
from pg_stat_activity
where backend_type = 'client backend';
Core metrics
Session state metrics
| Metric | Type | Description |
|---|---|---|
pg_stat_activity_count | Gauge | Sessions by state |
pg_stat_activity_max_tx_duration_seconds | Gauge | Longest running transaction |
pg_stat_activity_oldest_query_seconds | Gauge | Oldest active query duration |
Wait event metrics
| Metric | Type | Description |
|---|---|---|
pg_wait_event_count | Gauge | Sessions waiting by event type |
pg_wait_event_activity_count | Gauge | Sessions in activity wait states |
Labels
Session state labels
| Label | Values | Description |
|---|---|---|
state | active, idle, idle in transaction, idle in transaction (aborted), fastpath function call, disabled | Session state |
datname | Database name | Target database |
usename | User name | Connected user |
Wait event labels
| Label | Values | Description |
|---|---|---|
wait_event_type | CPU, IO, Lock, LWLock, BufferPin, Activity, Extension, Client, IPC, Timeout | Wait category |
wait_event | Various | Specific wait event |
Wait event categories
CPU
On-CPU processing, no actual wait:
| Event | Description |
|---|---|
CPU | Query execution on CPU |
IO
Disk I/O operations:
| Event | Description |
|---|---|
DataFileRead | Reading data file blocks |
DataFileWrite | Writing data file blocks |
DataFileExtend | Extending data file |
DataFileFlush | Flushing data file |
WALRead | Reading WAL |
WALWrite | Writing WAL |
WALSync | Syncing WAL to disk |
Lock
Row and table-level locks:
| Event | Description |
|---|---|
relation | Table lock wait |
tuple | Row lock wait |
transactionid | Transaction lock wait |
virtualxid | Virtual transaction lock |
LWLock
PostgreSQL internal lightweight locks:
| Event | Description |
|---|---|
buffer_content | Buffer content lock |
buffer_mapping | Buffer mapping lock |
WALInsert | WAL insertion lock |
lock_manager | Lock manager lock |
ProcArray | Process array lock |
BufferPin
Buffer pinning waits:
| Event | Description |
|---|---|
BufferPin | Waiting for buffer pin |
Activity
Background process waits:
| Event | Description |
|---|---|
LogicalLauncherMain | Logical replication launcher |
AutoVacuumMain | Autovacuum launcher |
BgWriterMain | Background writer |
CheckpointerMain | Checkpointer process |
WalWriterMain | WAL writer |
Common queries
Sessions by state
sum by (state) (pg_stat_activity_count)
Wait events distribution
sum by (wait_event_type) (pg_wait_event_count)
Active (non-idle) sessions
sum(pg_stat_activity_count{state!~"idle.*"})
Sessions waiting on locks
sum(pg_wait_event_count{wait_event_type="Lock"})
I/O wait ratio
sum(pg_wait_event_count{wait_event_type="IO"})
/
sum(pg_stat_activity_count{state="active"})
Long-running transactions
pg_stat_activity_max_tx_duration_seconds > 300
Dashboard usage
These metrics are used in:
- 01. Node overview — Active session history
- 04. Wait events — Wait event deep-dive
- 13. Lock contention — Lock analysis
Troubleshooting
No wait event data
-
Verify pgwatch is collecting from pg_stat_activity:
docker compose logs pgwatch | grep -i "stat_activity" -
Check monitoring user permissions:
grant pg_read_all_stats to postgres_ai_mon;
Wait events show "unknown"
Some wait events may not be captured if the session state changes between sampling intervals. This is normal for very short waits.
High "idle in transaction" count
Indicates connection leaks or application issues:
select pid, usename, state, query_start, query
from pg_stat_activity
where state = 'idle in transaction'
order by query_start;
Related metrics
- pg_stat_statements — Query-level metrics
- Table metrics — Table access patterns