PostgreSQL Lock Wait Analysis

Safely map blocked sessions to their blockers. Continuously monitor lock-wait duration and recurrence across workloads.

2026-10-01 · 2 min read

Why this problem matters

Lock waits can increase query latency and cause connections to accumulate in chains. Optimizing the blocked statement may not help until the root blocking transaction is addressed.

How to diagnose it

Use pg_blocking_pids() to find direct blockers and inspect transaction age on both sides. Do not reduce the relationship to one row when multiple blockers or parallel workers exist.

The query maps direct blocker PIDs to the activity view. Results are instantaneous, and lock relationships may change while it runs.

SELECT a.pid AS blocked_pid, a.usename AS blocked_user,
       b.pid AS blocking_pid, b.usename AS blocking_user,
       a.wait_event_type, a.wait_event,
       clock_timestamp() - a.query_start AS blocked_for
FROM pg_stat_activity AS a
CROSS JOIN LATERAL unnest(pg_blocking_pids(a.pid)) AS p(blocking_pid)
JOIN pg_stat_activity AS b ON b.pid = p.blocking_pid
ORDER BY blocked_for DESC;

A safe solution approach

Shorten transactions, access objects in a consistent order, and keep user interaction outside open transactions. Consider session intervention only after verifying ownership and rollback impact.

Why continuous monitoring matters

moon keeps lock-wait duration and recurrence continuously visible with low overhead. Slack, PagerDuty, and webhook channels can surface growing blocking chains.

Frequently asked questions

Is the blocking session always at fault?

No, a valid transaction may briefly hold a necessary lock. Evaluate the issue through duration, recurrence, and affected workload.

How does moon help with this problem?

moon continuously observes SQL Server, PostgreSQL, and MongoDB signals, helping teams evaluate the problem as a trend instead of relying on a one-time check.