Skip to main content

django-safemigrate: Safely run migrations before deployment

Latest Version Build status Code Coverage Code style: black

django-safemigrate adds a safemigrate command to Django to allow for safely running a migration command when deploying.

Usage

Install django-safemigrate, then add this to the INSTALLED_APPS in the settings file:

INSTALLED_APPS = [
    # ...
    "django_safemigrate",
]

Then mark any migration that may be run during a pre-deployment stage, such as a migration to add a column.

from django_safemigrate import Safe

class Migration(migrations.Migration):
    safe = Safe.before_deploy

At this point you can run the safemigrate Django command to run the migrations, and only these migrations will run. However, if migrations that are not safe to run before the code is deployed are dependencies of this migration, then these migrations will be blocked, and the safemigrate command will fail with an error.

When the code is fully deployed, just run the normal migrate Django command, which still functions normally. For example, you could add the command to the release phase for your Heroku app, and the safe migrations will be run automatically when the new release is promoted.

Safety Options

There are three options for the value of the safe property of the migration.

  • Safe.before_deploy

    This migration is only safe to run before the code change is deployed. For example, a migration that adds a new field to a model.

  • Safe.after_deploy

    This migration is only safe to run after the code change is deployed. For example, a migration that removes a field from a model.

    By specifying a delay parameter, you can specify when a Safe.after_deploy migration can be run with the safemigrate command. For example, if it’s desired to wait a week before applying a migration, you can specify Safe.after_deploy(delay=timedelta(days=7)).

    The delay is used with the datetime when the migration is first detected. The detection datetime is when the safemigrate command detects the migration in a plan that successfully runs. If the migration plan is blocked, such when a Safe.after_deploy is in front of a Safe.before_deploy, no migrations are marked as detected.

    Note that a Safe.after_deploy migration will not run the first time it’s encountered.

  • Safe.always

    This migration is safe to run before and after the code change is deployed. This is the default that is applied if no safe property is given. For example, a migration that changes the help_text of a field.

Pre-commit Hook

To get the most from django-safemigrate, it is important to make sure that all migrations are marked with the appropriate safe value. To help with this, we provide a hook for use with pre-commit. Install and configure pre-commit, then add this to the repos key of your .pre-commit-config.yaml:

repos:
    -   repo: https://github.com/ryanhiebert/django-safemigrate
        rev: "6.0"
        hooks:
        -   id: check

Nonstrict Mode

Under normal operation, if there are migrations that must run before the deployment that depend on any migration that is marked to run after deployment, the command will raise an error to indicate that there are protected migrations that should have already been run, but have not been, and are blocking migrations that are expected to run.

In development, however, it is common that these would accumulate between developers, and since it is acceptable for there to be downtime during the transitional period in development, it is better to allow the command to continue without raising.

To enable nonstrict mode, add the SAFEMIGRATE setting:

SAFEMIGRATE = "nonstrict"

In this mode safemigrate will run all the migrations that are not blocked by any unsafe migrations. Any remaining migrations can be run after the fact using the normal migrate Django command.

Disabled Mode

To disable the protections of safemigrate entirely, add the SAFEMIGRATE setting:

SAFEMIGRATE = "disabled"

In this mode safemigrate will migrations as if they were using the normal migrate Django command.

Contributing

To get started contributing, you’ll want to clone the repository, install dependencies with uv, and set up pre-commit.

git clone git@github.com:ryanhiebert/django-safemigrate.git
cd django-safemigrate
uv sync
pre-commit install

To run the tests use:

uvx --with tox-uv tox

To publish a new version:

  1. Find and replace all instances of the previous version with the new version.

  2. Commit and push that to origin.

  3. Tag the commit with the new version git tag 1.0 and push that to origin.

  4. Create the new release on GitHub. It will be published to PyPI automatically.

Metadata

Release files for django-safemigrate 6.0

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

Source distribution (sdist)

Source distribution for django-safemigrate 6.0
File Size Uploaded Provenance
django_safemigrate-6.0.tar.gz 15.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-safemigrate 6.0
File Interpreter ABI Platform
django_safemigrate-6.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.2 kB

Release files / django_safemigrate-6.0.tar.gz

Download URL django_safemigrate-6.0.tar.gz
Size 15.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b15e5a7469a2c26f7e7a2657e39cf63cec939ae9ccda0dc4d59a7f9eb7766cc4
BLAKE2b-256 checksum
How to use checksums
3bc7bc6253f7922a3d6664ac78b4dc1742e674794da1010c4ce69e8b924e33d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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 Jun 3, 2025.

Transparency log

Release files / django_safemigrate-6.0-py3-none-any.whl

Download URL django_safemigrate-6.0-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4fd744a43a2db677e0e8aea2faf8aeb324101c11547ae6f963bd77e47fa3f4ff
BLAKE2b-256 checksum
How to use checksums
59e9b807cfaf6d4d2e82dee4c31c1a0bb9b082c497de9a5e1193a49573b5a07a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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 Jun 3, 2025.

Transparency log

Security for django-safemigrate 6.0

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 django_safemigrate-6.0.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 Jun 3, 2025.

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.

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