Find the statements in your Rails, Django or raw SQL migrations that take a table-blocking Postgres lock - and the safe rewrite - before you deploy. Runs entirely in your browser — nothing is uploaded.
Same engine as the VS Code extension, byte for byte.
Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.
VS Code MarketplaceOpen VSX (Cursor, VSCodium)npmMCP server (npx)Docker Hubext install ReadyStack.pg-migration-lock-lint npx @readystack/pg-migration-lock-lint <file> npx @readystack/pg-migration-lock-lint --mcp
Team? One key for every ReadyStack linter, 5 seats, $149 once
Check every migration in the workspace in one pass, export the review as Markdown or JSON for the change ticket, and fail CI on an exit code.
One payment, one licence key for this tool. The key is shown right after payment.
Independent Postgres consultancies bill migration and lock review at $150/hour and up; this is one review, priced once.
Buy the full version — $29· ReadyStack
Real numbers from this tool, line by line.

22 findings in a 20-statement migration. That is what a Rails engineer on a live orders table gets back from the file an assistant wrote in four seconds.
The migration is unremarkable. Add a tenant_id column, tighten amount_cents to numeric(12,2), add a foreign key to tenants, add a unique constraint on external_ref, build an index on tenant_id, rename legacy_total, drop legacy_notes, backfill the new column, clear an events table. Twenty statements between BEGIN and COMMIT. Nothing in it is wrong SQL. Every statement runs. That is the problem: the lock behaviour is not in the text.
Sixteen of the 22 findings are at error severity, meaning writes stop or the statement aborts outright. ALTER COLUMN amount_cents TYPE numeric(12,2) rewrites the whole table and every index on it while holding ACCESS EXCLUSIVE. CREATE INDEX without CONCURRENTLY holds SHARE, so reads continue and every INSERT, UPDATE and DELETE waits for the build. ADD CONSTRAINT ... FOREIGN KEY without NOT VALID takes ACCESS EXCLUSIVE on the child table and SHARE ROW EXCLUSIVE on the parent while it scans existing rows. ADD COLUMN tenant_id bigint NOT NULL with no default does not block at all - it fails, SQLSTATE 23502, because the table already has rows. And CREATE INDEX CONCURRENTLY, the correct form, aborts with 25001 when it is sitting inside the BEGIN/COMMIT the generator wrapped everything in.
The finding that matters most is the one that is not a statement. There is no lock_timeout anywhere in the file. A DDL statement that cannot get its lock does not fail; it waits. And while it waits at the head of the lock queue, every query that arrives after it waits too, including the plain SELECTs that were perfectly compatible with whatever is already running. One analytics query holding a read lock plus one ALTER TABLE behind it is enough to make a healthy table unreadable. SET lock_timeout = '3s' turns that outage into a retry.
Version matters and the text does not tell you the version. ADD COLUMN x int DEFAULT 0 rewrote the table on PostgreSQL 10 and has been instant since 11, so flagging it now is noise - the rule set leaves it alone. SET NOT NULL skips its table scan on 12 and later, but only when a validated CHECK (x IS NOT NULL) already exists, which generated migrations almost never add first. REINDEX CONCURRENTLY exists from 12. Advice written before those releases is still what most of this code is imitating. PostgreSQL 14 receives its final minor release in November 2026, so a lot of teams are writing their 14-to-17 upgrade migrations right now.
The free tools each see one half of the problem. strong_migrations reads the Rails DSL and nothing else. squawk parses raw SQL and nothing else. Neither reads a Django operations list, where AddIndex, AlterField and a RunPython backfill inside an atomic migration carry exactly the same locks. Both run in CI, after the migration is already written, already committed, already in a pull request with three approvals.
Postgres Migration Lock Lint reads the file in the editor. 36 rules, one message each, naming the lock mode, the SQLSTATE where there is one, and the rewrite. Raw .sql, Rails ActiveRecord::Migration, Django migrations.Migration. The same schema change, split so nothing blocks - constant default, CHECK NOT VALID then VALIDATE, unique index built CONCURRENTLY then attached USING INDEX, a batched backfill with a WHERE - returns zero findings.
Free tier: the file you have open, all 36 rules. The same rules run in the browser on pasted text, with nothing uploaded, at getreadystack.com/tools/pg-migration-lock-lint.
It reads a migration file and names every statement that takes a lock Postgres will not share, such as ACCESS EXCLUSIVE on a table rewrite or SHARE on a plain CREATE INDEX. 36 rules, PostgreSQL 12-17. On the bundled 20-statement sample migration it returns 22 findings, 16 of them at error severity; the hand-split version of the same schema change returns 0 findings.
Rails and Django engineers who deploy to a Postgres database that has real traffic, and anyone reviewing raw .sql migrations written by an assistant. It is aimed at the person who runs the deploy and gets paged when a table stops answering, not at a greenfield project where every table is empty.
strong_migrations reads only the Rails DSL, squawk reads only raw SQL, and both run in CI after the migration is already in a pull request. Neither reads a Django operations list. This runs on the file in your editor, across all three formats, before the branch exists, and it knows which forms became safe in PostgreSQL 11 and 12.
Free: the migration file you have open, checked against all 36 rules, with the full message and the safe rewrite. No key, no limit on how often. The full version adds scope and ownership: every migration in the workspace in one pass, the review exported as Markdown or JSON for the change ticket, and an exit code for CI.
Independent Postgres consultancies bill migration and lock review at $150 an hour and up, and an incident review costs more than that once on-call time is counted. This is $29 once,. The free tier covers the file you are editing right now at no cost at all.
A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Postgres Migration Lint - locks and downtime (ALTER TABLE, C checks the file you open against 36 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.
One question, answered by the person who built it. Your email only if you want the answer sent.
Paste this code into your page. It runs in your visitor’s browser and stays up to date. Nothing your visitors type is stored.
For businesses: your name and logo instead of ours, and each visitor’s result + e-mail in your inbox (only when they tick consent) — Pro from $19/month. See Pro →