lockTimeoutWarning

Diagnostic Category: lint/safety/lockTimeoutWarning

Since: vnext

Note

This rule is recommended. A diagnostic error will appear when linting your code.

Sources: - Inspired from: eugene/E9

Description

Taking a dangerous lock without setting a lock timeout can cause indefinite blocking.

When a statement acquires a lock that would block common operations (like SELECT, INSERT, UPDATE, DELETE), it can cause the database to become unresponsive if another transaction is holding a conflicting lock while idle in transaction or active. This is particularly dangerous for:

  • ALTER TABLE statements (acquire ACCESS EXCLUSIVE lock)
  • CREATE INDEX without CONCURRENTLY (acquires SHARE lock)

Setting a lock timeout ensures that if the lock cannot be acquired within a reasonable time, the statement will fail rather than blocking indefinitely.

Examples

Invalid

ALTER TABLE users ADD COLUMN email TEXT;
code-block.sql:1:1 lint/safety/lockTimeoutWarning ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ! Statement takes ACCESS EXCLUSIVE lock on public.users without lock timeout set.

  > 1 │ ALTER TABLE users ADD COLUMN email TEXT;
      │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    2 │ 

  i This can block all operations on the table indefinitely if another transaction holds a conflicting lock.

  i Run 'SET LOCAL lock_timeout = '2s';' before this statement and retry the migration if it times out.


CREATE INDEX users_email_idx ON users(email);
code-block.sql:1:1 lint/safety/lockTimeoutWarning ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ! Statement takes SHARE lock on public.users while creating index users_email_idx without lock timeout set.

  > 1 │ CREATE INDEX users_email_idx ON users(email);
      │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    2 │ 

  i This blocks writes to the table indefinitely if another transaction holds a conflicting lock.

  i Run 'SET LOCAL lock_timeout = '2s';' before this statement, or use CREATE INDEX CONCURRENTLY to avoid blocking writes.


Valid

-- Use CONCURRENTLY to avoid taking dangerous locks
CREATE INDEX CONCURRENTLY users_email_idx ON users(email);

How to configure


{
  "linter": {
    "rules": {
      "safety": {
        "lockTimeoutWarning": "error"
      }
    }
  }
}