A useful checker appeared at the right moment.
Safe Not Safe puts a PostgreSQL migration into a browser-based editor and asks for table size and transaction-wrapper context. The interface ships examples for risky and safer statements, plus views for problems, output, parse tree, and rule engine.[1] That is a better review surface than approving DDL because it looks familiar.
The tool also makes a point that generic SQL review often misses. The same statement can carry different operating risk on a small idle table and a hot multi-million-row table. Context belongs beside the statement.
A migration is not safe because the syntax looks boring. It is safe enough for one named production shape, under one measured stop policy.
The lock queue is part of the change.
PostgreSQL says most commands acquire locks automatically. Its strongest table lock, ACCESS EXCLUSIVE, conflicts with every table-level lock mode. The documentation also says only that mode blocks a plain SELECT.[2] The important question is not just which lock a statement needs. Ask how long it can wait to acquire that lock and how much work can queue behind it.
A migration wrapped in a transaction can turn a short statement into a long lock lifetime. A blocked migration can also become the head of a line. Put lock_timeout, statement_timeout, transaction scope, and an abort owner in the deployment packet. Defaults are not a stop policy.
Safer forms still have conditions.
PostgreSQL documents that a standard index build blocks writes until it finishes. CREATE INDEX CONCURRENTLY allows inserts, updates, and deletes to continue, but PostgreSQL calls out caveats and extra work for that mode.[3] "Concurrent" is not a universal pass stamp.
Strong Migrations catches operations it classifies as potentially dangerous and suggests safer forms. Its own test is concrete. The operation either blocks reads or writes for more than a few seconds after lock acquisition, or has a good chance of causing application errors.[4] That catches known patterns. It does not observe your current blockers, replica lag, application release order, or cancel path unless you supply or test them.
Make the review packet executable.
- Freeze the statement. Save the exact SQL and database version. Framework methods are not the final lock request.
- Set the wait budget. Record lock and statement timeouts. Name the person or automation allowed to abort.
- Describe production. Record table size, write rate, long transactions, replicas, and whether the migration runner wraps DDL in a transaction.
- Prove the exit. Rehearse cancel or rollback on a production-shaped copy. Save lock observations, duration, application errors, and recovery time.
Run the static checker before the deploy. Then run the operational drill. The checker finds known statement hazards. The drill tests the environment that will carry the statement.