Guides / You have unapplied migrations / relation does not exist

You have unapplied migrations / relation does not exist

You deployed new code and now see You have N unapplied migration(s), or pages crash with relation "app_model" does not exist (no such table on SQLite). The code and the database schema are out of step: the new code expects tables or columns that the database does not have yet.

What it means

Migrations are the scripts that change your database to match your models. Deploying code does not run them. If the new code reaches production before migrate has run, any query that touches a new table or column fails. The warning text comes from runserver:

You have 3 unapplied migration(s). Your project may not work properly until you apply the
migrations for app(s): myapp. Run 'python manage.py migrate' to apply them.

In production you usually see the crash instead: django.db.utils.ProgrammingError: relation "myapp_order" does not exist, or column "shipped_at" of relation "myapp_order" does not exist.

Why it happens

  1. migrate is not part of your deploy. It lives in somebody's memory, and this release was the first one that needed it.
  2. The migration files were never committed. makemigrations ran on your laptop, and the migrations/ folder is gitignored or the new file wasn't added.
  3. It ran against the wrong database. A DATABASE_URL in the deploy step that differs from the one the app uses, or a staging database migrated instead of production.
  4. New code started before migrate finished. Common with several instances, or when migrate sits in the container's start command and the rest of the app begins serving immediately.

The fix

Right now, run the migrations against the production database, from the same code that is deployed:

python manage.py showmigrations      # [ ] marks what is not applied yet
python manage.py migrate --noinput

If showmigrations shows nothing pending but a table is still missing, a migration file was never committed. On your machine run python manage.py makemigrations --check --dry-run; it exits non-zero when models have changes without a migration. Commit the file and deploy again.

Making it stick in production

Make migrations a step of the release, so it can't be forgotten and runs once:

  1. Build the new version.
  2. Run python manage.py migrate --noinput once against the production database.
  3. Start the new instances only if it succeeded, and stop the release if it failed.
# deploy.sh
set -euo pipefail
python manage.py migrate --noinput
python manage.py check --deploy --fail-level WARNING
# ...then restart gunicorn / roll out the new containers

Avoid putting migrate && gunicorn ... in the container's start command when you run more than one instance. Every instance would run the migration at the same time, and some will start serving before the schema is ready. A single release step avoids both.

To keep the old version healthy while the new schema is rolling out, split risky changes in two deploys. First add the column or table (nullable, with a default) and ship code that works with and without it. Remove or rename things in a later release, once no running code uses the old shape. Add this to CI so a missing migration never reaches production:

python manage.py makemigrations --check --dry-run
python manage.py migrate --check   # exits 1 if the database has unapplied migrations

If a deploy has to be undone after a migration, read How to roll back a Django deploy (and bad migrations).

Or skip it

Django Cloud runs your release command, migrate --noinput by default, before the new version starts. If the new version can't start or pass its health check, the previous release keeps serving your visitors.

pip install djangocloud-cli
djangocloud deploy

Get startedSee pricing

Free plans are available for students, AWS Activate startups, open-source, non-profit and research projects. See how Django Cloud compares with other ways to host Django.

Django is a registered trademark of the Django Software Foundation. Django Cloud is not affiliated with or endorsed by it. Found a mistake in this guide? Tell us and we will fix it.