FluentDBFluentDB
PostgreSQL errors

PostgreSQL: deadlock detected

ERRORSQLSTATE 40P01deadlock_detected
ERROR: deadlock detected

Two transactions each hold a lock the other needs, so neither can proceed. Postgres breaks the tie by aborting one of them. The durable fix is to acquire locks in a consistent order, keep transactions short, and retry on this error.

What this error means

A deadlock happens when transaction A holds a lock on one row and wants a second, while transaction B holds the second and wants the first. Neither can move, so Postgres detects the cycle and cancels one transaction with this error. The DETAIL and server log show the two statements involved.

It is a concurrency problem, not a data problem, and it is expected under contention. Well-behaved apps retry the aborted transaction.

How to fix it

01

Transactions lock rows in different orders

Always acquire locks in the same order across every code path, for example by updating the lower id first.

02

The transaction is retryable

Catch SQLSTATE 40P01 and retry the whole transaction, ideally with a short backoff.

03

You need to see what collided

The server log records both queries. The DETAIL line names the two backend PIDs and the locks they waited on.

text
-- check the server log around the deadlock for the two statements

How to avoid it next time

  • Use a consistent lock ordering everywhere, and keep transactions short.
  • Keep the retry: you cannot guarantee zero deadlocks under real concurrency.

Frequently asked questions

Is a deadlock a bug in Postgres?

No. It is a normal outcome of concurrent transactions competing for locks in different orders. Postgres resolves it by aborting one; your app should retry.

How do I stop deadlocks entirely?

Acquire locks in a consistent order everywhere and keep transactions short. You cannot fully guarantee zero, so keep retry logic.

Stop struggling with SQL

Use FluentDB, the AI database client for macOS.