A linter that reads your database migrations the way Postgres will run them, and tells you what will lock before you merge.

migrail catches the migrations that take production down: an index built without CONCURRENTLY, a foreign key added without NOT VALID, a type change that rewrites a 50 GB table under an exclusive lock. Every finding names the lock mode, what it blocks, why Postgres does it, and the fix. v0.1 ships 25 rules for PostgreSQL 12 to 18 and reads nine migration tools with no config file, and every lock claim in it is verified against real databases in CI. The end goal is a checker that speaks your framework, reads your application code before you drop a column, and estimates real impact from real table sizes. Free, Apache-2.0, no account.
Teams take production down with migrations that read fine in review. CREATE INDEX without CONCURRENTLY holds a lock that blocks every insert, update and delete until the index finishes building. A column rename breaks the pods still serving traffic on the old code during a rolling deploy. A type change rewrites a 50 GB table while holding an exclusive lock.
None of that is visible in the diff. It is visible in the PostgreSQL locking documentation, and code review is not the moment anyone opens it.
migrail parses every migration with the same parser PostgreSQL uses and reports what the database will do with it. Each finding names the lock mode, the operations it blocks, why Postgres behaves that way, and the fix as a statement you can paste:
CREATE INDEX CONCURRENTLY idx_orders_created_at ON orders (created_at);It runs with no arguments and no config file. It finds the migrations directory, detects which tool wrote it, works out the git base branch, and checks only what changed on your branch.

A linter that is wrong about a lock is worse than no linter. Tell someone a safe statement is dangerous and they learn to ignore you. Tell them a dangerous one is safe and you caused the outage.
So every lock mode and rewrite claim in migrail is verified against real databases. The harness starts PostgreSQL 12 through 18 in Docker, runs each statement, reads back the locks the server actually took, and compares them with what the model predicted. A disagreement fails the build. make lockverify runs it locally and CI runs it nightly.
v0.1 is released. It covers PostgreSQL 12 to 18 with 25 rules across locks, table rewrites, transaction mistakes, code compatibility and data loss. It reads golang-migrate, goose, Atlas, Flyway, Prisma, Drizzle, dbmate, sqitch and plain SQL directories, including each tool’s own conventions for transaction mode.
Output is a compiler-style diagnostic with a code frame, or JSON for anything that needs to read it. It installs as a single binary through Homebrew or a checksum-verified script, on macOS, Linux and Windows for amd64 and arm64. Every release publishes checksums, a cosign signature and an SBOM.

Most of what separates migrail from a Postgres SQL linter is still ahead of it.
v0.2 adds native adapters for Django, Alembic, Rails, Laravel, EF Core, Knex, TypeORM, Sequelize and Liquibase, plus a capture mode that supports any other tool by running its migration command against a throwaway database and reading the SQL it emits. Fixes then arrive in your framework’s syntax. Rails users get disable_ddl_transaction! and algorithm: :concurrently. Django users get AddIndexConcurrently and atomic = False.
v0.3 reads your application code. Before you drop or rename a column, migrail searches your Go, Python, Ruby, TypeScript, PHP, Java and C# for the queries and models that still use it, so it can tell you whether the migration is safe to ship ahead of the code change. With a read-only connection to staging it also estimates impact from real table sizes, for example that a rewrite on a 41 million row table will hold its exclusive lock for roughly four to nine minutes.
v1.0 is the full PostgreSQL catalogue with stable rule IDs and schemas. MySQL and MariaDB follow in v2, then SQL Server, SQLite and CockroachDB.
Atlas moved its Postgres lock checks behind a login and a paid tier. squawk is free and good, and its own documentation says it has no special support for Django or any other ORM. strong_migrations is excellent and Rails only.
The checks that stop you breaking production should not be the paid tier. In migrail they never will be: Apache-2.0, no account, no config file, no feature gating in the CLI or in CI.
Need something like this built?
Send me the details, or book a 15 minute call from the contact page.