PostgreSQL error: canceling statement due to lock timeout

ERROR:  canceling statement due to lock timeout

The statement waited for a lock longer than lock_timeout allows and gave up. Unlike most errors on this list, this one usually means a safety mechanism worked: failing fast on a lock is almost always better than queueing behind it — especially for DDL.

What this error means

Why failing fast matters is about the queue, not the waiter: an ALTER TABLE needs an ACCESS EXCLUSIVE lock. While it waits behind some long-running query, every new query on that table — including plain SELECTs — queues behind it. A stuck migration can freeze a production table within seconds. lock_timeout converts that scenario into a quick, retryable failure.

Do not confuse it with statement_timeout: that bounds total runtime; lock_timeout bounds a single lock wait and has its own SQLSTATE (55P03).

Common causes

How to diagnose it

-- Chi blocca chi, adesso:
SELECT waiting.pid, waiting.query AS waiting_query,
       blocking.pid AS blocking_pid, blocking.query AS blocking_query,
       now() - blocking.xact_start AS blocking_xact_age
FROM pg_stat_activity waiting
JOIN pg_stat_activity blocking
  ON blocking.pid = ANY (pg_blocking_pids(waiting.pid));

Also set log_lock_waits = on: waits longer than deadlock_timeout get logged with both sides, giving you a history of contention, not just the live view.

How to fix it

🔍 The other way lock waits end badly: deadlock detected.