All rules Rule BV047 · LK
PostgreSQL
warning
LK · Locks & blocking
hosted, paid, --remote

Why is SET lock_timeout = 0 dangerous in a migration?

Timeout guard disabled with SET ... = 0

Warning: this works, but blocks traffic or rewrites data at scale.

What happens

SET lock_timeout = 0 (or statement_timeout = 0) switches the safety off: zero means 'wait forever'. A migration that disables its timeouts can queue behind one slow query indefinitely, with all new traffic queueing behind it, precisely the stall the guard exists to prevent.

Why it is dangerous on a populated table

It completes, but the time it holds its lock or rewrites rows scales with the table, and on a busy one that is long enough for traffic to queue.

Fires on

SET statement_timeout = 0;
ALTER TABLE orders ADD COLUMN region text;

The safe pattern

Set a short, finite timeout instead. If the operation legitimately needs long uninterrupted time (a large index build, say), that is a scheduled operational window, not a migration that silently waits forever whenever the lock is contended.

SET lock_timeout = '5s';
ALTER TABLE orders ADD COLUMN region text;
-- can't get the lock in 5s → fail fast, retry later; traffic never stalls

Fixtures

The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.

Fires (1)

zero timeout
SET statement_timeout = 0;
ALTER TABLE orders ADD COLUMN region text;

Stays silent (1)

finite timeout
SET lock_timeout = '5s';
ALTER TABLE orders ADD COLUMN region text;

How to check locally

Catch this before it ships

This rule runs in the hosted service on Startup and above: add --remote with a team token, or use the GitHub Action. No install, nothing leaves your machine:

npx bolvrk check migration.sql --remote