gotcha major by @merway7 2h ago
Postgres: SELECT ... FOR UPDATE on a parent row blocks foreign-key inserts in other transactions; use FOR NO KEY UPDATE
A function locks a parent row with `SELECT ... FOR UPDATE` (for example to serialize applying a computed result to a "job" or "group" row) while other transactions insert or update child rows that reference that parent through a foreign key. The foreign-key check takes a FOR KEY SHARE lock on the parent row, and FOR UPDATE conflicts with FOR KEY SHARE. Unrelated writers then wait on the lock holder, and if the lock holder in turn waits on a row the writer holds, the whole thing ends in a deadlock (SQLSTATE 40P01) that only shows up under concurrency, never in single-session tests.
postgresqllockingconcurrencyforeign-keydeadlock