Skip to main content

migra: PostgreSQL migrations made almost painless

Schema migrations are without doubt the most cumbersome and annoying part of working with SQL databases. So much so that some people think that schemas themselves are bad!

But schemas are actually good. Enforcing data consistency and structure is a good thing. It’s the migration tooling that is bad, because it’s harder to use than it should be. migra is an attempt to change that, and make migrations easy, safe, and reliable instead of something to dread.

Migra supports PostgreSQL >= 9.4. Known issues exist with earlier versions.

Full documentation

Official documentation is at migra.readthedocs.io

How it Works

Think of migra as a diff tool for schemas. Suppose database A and database B have similar but slightly different schemas. migra will detect the differences and output the SQL needed to transform A to B.

This includes changes to tables, views, functions, indexes, constraints, enums, sequences, and installed extensions.

You can use migra as a library to build your own migration scripts, tools, etc. Installing migra also installs the migra command, so you can use it as follows:

$ migra postgresql:///a postgresql:///b
alter table "public"."products" add column newcolumn text;

alter table "public"."products" add constraint "x" CHECK ((price > (0)::numeric));

If b is the target schema, then a new column and constraint needs to be applied to a to make it match b’s schema. Once we’ve reviewed the autogenerated SQL and we’re happy with it, we can apply these changes as easily as:

$ migra --unsafe postgresql:///a postgresql:///b > migration_script.sql
# Then after careful review (obviously)...
$ psql a --single-transaction -f migration_script.sql

Migration complete!

IMPORTANT: Practice safe migrations

Migrations can never be fully automatic. As noted above ALWAYS REVIEW MIGRATION SCRIPTS CAREFULLY, ESPECIALLY WHEN DROPPING TABLES IS INVOLVED.

Best practice is to run your migrations against a copy of your production database first. This helps verify correctness and spot any performance issues before they cause interruptions and downtime on your production database.

migra will deliberately throw an error if any generated statements feature the word “drop”. This safety feature is by no means idiot-proof, but might prevent a few obvious blunders.

If you want to generate “drop …” statements, you need to use the --unsafe flag if using the command, or if using the python package directly, set_safety( to false on your Migration object.

Python Code

Here’s how the migra command is implemented under the hood (with a few irrelevant lines removed).

As you can see, it’s pretty simple (S here is a context manager that creates a database session from a database URL).

from migra import Migration
from sqlbag import S

with S(args.dburl_from) as s0, S(args.dburl_target) as s1:
    m = Migration(s0, s1)

    if args.unsafe:
        m.set_safety(False)

    m.add_all_changes()
    print(m.sql)

Here the code just opens connections to both databases for the Migration object to analyse. m.add_all_changes() generates the SQL statements for the changes required, and adds to the migration object’s list of pending changes. The necessary SQL is now available as a property.

Documentation

migra is in early alpha and documentation is scarce so far. We are working on remedying this. Watch this space.

Features and Limitations

migra plays nicely with extensions. Schema contents belonging to extensions will be ignored and left to the extension to manage.

Only SQL/PLPGSQL functions are confirmed to work so far. migra ignores functions that use other languages.

Installation

Assuming you have pip installed, all you need to do is install as follows:

$ pip install migra

If you don’t have psycopg2 (the PostgreSQL driver) installed yet, you can install this at the same time with:

$ pip install migra[pg]

Metadata

Release files for migra 1.0.1489900901

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

Source distribution (sdist)

Source distribution for migra 1.0.1489900901
File Size Uploaded
migra-1.0.1489900901.tar.gz 6.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for migra 1.0.1489900901
File Interpreter ABI Platform
migra-1.0.1489900901-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 16.8 kB

Release files / migra-1.0.1489900901.tar.gz

Download URL migra-1.0.1489900901.tar.gz
Size 6.2 kB
Tags Source
SHA-256 checksum
How to use checksums
a47797641ed40555d52ef5c15511a9a5124461b343623b9f875472f3ae04840c
BLAKE2b-256 checksum
How to use checksums
e813122c7ccd2adbbfbbdeffa67be1e3398ab84e8c71cf71441978fe35220405
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / migra-1.0.1489900901-py2.py3-none-any.whl

Download URL migra-1.0.1489900901-py2.py3-none-any.whl
Size 10.6 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
847e6e4b7b44a2b146db10e4d4b6203f3b46d9ef0d64b71f12b828cf8ce15404
BLAKE2b-256 checksum
How to use checksums
44ec67a103df6845014372b77ee231eb19b9a7cec56302710711ed73266a2d1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

1.0.1489900901 This release

2 release files

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