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.2

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.2
File Size Uploaded Provenance Actions
migsafe_pg-0.1.2.tar.gz 10.1 kB With provenance Details for migsafe_pg-0.1.2.tar.gz

Built distribution (wheel)

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

Total release size: 19.9 kB

Release files / migsafe_pg-0.1.2.tar.gz

Download URL migsafe_pg-0.1.2.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e4ec11454d410bbd86e1f5ed2979ba9311bea817acf2c729bfb526bebb46a7b6
BLAKE2b-256 checksum
How to use checksums
ca7d6fbe61b59829404a83c45e9deca52a5daf590f77a696a4b144ddc9cf78d3
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.2-py3-none-any.whl

Download URL migsafe_pg-0.1.2-py3-none-any.whl
Size 9.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9fa449872a734f11995a188c86730abf00a87c8b2b889f8b0aee17bbf7a2e95b
BLAKE2b-256 checksum
How to use checksums
d6f66f8a5b41b6e31cce13a2c3067163b70b285668232950597b7a603c4592f1
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.2

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.2.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.2 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