Skip to main content

migsafe

This migration would have locked your users table. migsafe tells you before you merge it. Static analysis for PostgreSQL migrations: locks, rewrites, destructive steps, missing timeouts.

ci license: MIT postgres stars

migsafe demo

Install

pipx install git+https://github.com/mgkvibez/migsafe.git   # works today
pipx install migsafe-pg                                    # once the PyPI release is live

The distribution is published to PyPI as migsafe-pg because the short name is already taken by an unrelated project. The command, the import package and the repo are all still migsafe. Zero runtime dependencies, Python 3.9+. bash pipx install git+https://github.com/mgkvibez/migsafe.git


## Three ways to use it

```bash
# 1. Check one migration
migsafe check migrations/2026_10_29_add_user_flags.sql

# 2. Check the whole directory (fails the build on high and above)
migsafe check migrations/ --fail-on high

# 3. Machine-readable, for a bot or an agent skill
migsafe check migrations/ --json

Exit code is 2 when a finding at or above --fail-on exists, so migsafe check migrations/ && psql ... is safe by default.

Why it exists

ALTER TABLE users ADD COLUMN last_seen timestamptz DEFAULT now() is four words of difference from a statement that rewrites the whole table under an ACCESS EXCLUSIVE lock. It passes review because it looks like the fifty migrations before it. Then it runs at 14:00 and takes the site down for forty seconds, and everyone learns the same lesson the hard way.

The linter encodes that lesson: what takes a lock, what rewrites rows, what cannot be undone, and what to write instead.

How it works

Splits the file into statements — dollar-quoted blocks, string literals and comments are handled, so a ; inside a function body does not confuse it — then applies rules:

Severity Rule Why it matters
critical drop-table, drop-column, truncate data loss that a rollback does not undo after commit
critical unbounded-write UPDATE/DELETE with no WHERE touches every row
high volatile-default DEFAULT now() on ADD COLUMN rewrites the table
high add-not-null-column NOT NULL with no default fails on non-empty tables
high index-not-concurrent CREATE INDEX blocks writes for the whole build
high alter-column-type type changes rewrite the table and drop dependent indexes
high constraint-without-not-valid adding a FK or CHECK validates every row under a lock
medium unbatched-backfill, multiple-alter-ops, rename, set-not-null, no-timeout slower failure modes and lock pile-ups

It knows what the same file creates: an index on a table you are creating in this migration is not flagged, because there is nothing to lock yet.

Every finding carries the statement line and a fix you can paste.

Contributing

Read CONTRIBUTING.md. Tests:

python -m pytest -q

License

MIT. See LICENSE.

Metadata

Release files for migsafe-pg 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for migsafe-pg 0.1.1
File Size Uploaded Provenance Actions
migsafe_pg-0.1.1.tar.gz 10.1 kB With provenance Details for migsafe_pg-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for migsafe-pg 0.1.1
File Interpreter ABI Platform Actions
migsafe_pg-0.1.1-py3-none-any.whl Python 3 none any Details for migsafe_pg-0.1.1-py3-none-any.whl

Total release size: 19.9 kB

Release files / migsafe_pg-0.1.1.tar.gz

Download URL migsafe_pg-0.1.1.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f0ad1120a7cf014ba061d2151843c13495e26390f051ea19a0df05e1fd568865
BLAKE2b-256 checksum
How to use checksums
b5a335c256f45c2924aef493bbee1246522b9e3e13da847053a76c9a3f2316e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / migsafe_pg-0.1.1-py3-none-any.whl

Download URL migsafe_pg-0.1.1-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
60903a30c1bc2dc47e5fa577ff4a5f182962d41ab9cc824b54bb9a0fd1649dcb
BLAKE2b-256 checksum
How to use checksums
2bc51befab98d4f45f81561bcec990eb36f345cf5c9157163186134d1f01af2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for migsafe-pg 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for migsafe_pg-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page