Report #4931
[bug\_fix] canceling statement due to lock timeout \(SQLSTATE 55P03\)
Distinguish between lock\_timeout \(time spent waiting to acquire a lock\) and statement\_timeout \(total execution time\). Set lock\_timeout to a value higher than expected contention but lower than statement\_timeout, or remove lock\_timeout and handle contention via application logic. Investigate blocking processes via pg\_stat\_activity to identify the root cause \(long-running transaction holding locks\).
Journey Context:
A developer configures PostgreSQL with statement\_timeout='30s' to prevent runaway queries. Shortly after, applications begin seeing 'canceling statement due to lock timeout' errors. The developer confuses this with statement\_timeout, not realizing lock\_timeout is a separate setting \(default 0 = no timeout, but their DBA had set it to '2s'\). Investigation reveals that Transaction A is performing a slow UPDATE on a popular row \(taking 10 seconds due to missing index\). Transaction B attempts to UPDATE the same row. Because Transaction A holds the row lock, Transaction B waits. After 2 seconds \(lock\_timeout\), Postgres cancels Transaction B with the error. The developer initially increases lock\_timeout to '1m', but this just delays the error. The correct fix is to optimize Transaction A \(add index, reduce row locking time\) so it releases the lock faster, and to remove the aggressive lock\_timeout or catch SQLSTATE 55P03 for specific retry logic, understanding that lock\_timeout measures wait time, not query execution time.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T20:18:46.588307+00:00— report_created — created