Migrations & schema changes for Django in production
Applying Django migrations safely during deploys, and repairing migration history when it goes wrong.
Migrations change the schema under running code. In production that means keeping old and new code compatible, avoiding long locks on large tables, and having a plan when a migration fails halfway.
The guides cover the release strategy, safe schema changes, and fixing conflicts and inconsistent history.
Set it up
Guides that take this from nothing to running in production.
- Run Django Migrations as a Kubernetes Job
Run Django migrations exactly once per release on Kubernetes: a Job per image tag, waiting for completion in CI, lock timeouts, why init containers are risky, and handling failures.
- Migrate a Django Project From SQLite to PostgreSQL
Move a live Django project from SQLite to PostgreSQL without losing data: create the schema with migrate, transfer data with dumpdata and loaddata or pgloader, fix content types and sequences, and cut over with minimal downtime.
Run it well
Tuning, reliability, and operations once it works.
- Django Migration Strategy for Safe Deployments
A good app deploy can still fail if the database migration step is unsafe. That is the real problem behind many Django migration deployment issues in production.
- Run Schema Changes on Large Tables in Django Safely
Change large PostgreSQL tables from Django migrations without outages: lock_timeout, concurrent indexes, NOT VALID constraints, and batched backfills.
- Add Database Indexes in Django Without Locking Tables
Add PostgreSQL indexes to large tables in a live Django app without blocking writes: AddIndexConcurrently in non-atomic migrations, handling failed concurrent builds, finding missing indexes, and removing unused ones safely.
- Roll Back a Django Migration in Production
Undo a Django migration safely in production: migrate an app back to a previous migration, understand which operations are reversible, handle data loss from reverting added columns and data migrations, roll back code and schema in the right order, and prefer forward fixes.
- Squash Django Migrations Safely in Production
Squash long Django migration histories without breaking deployed environments: run squashmigrations, keep replaced migrations until every database has applied them, handle RunPython and elidable operations, update dependencies, and remove old files in a later release.
- Run a Django Data Migration on a Large Table
Backfill or transform millions of rows in Django without long locks or failed deploys: move heavy data changes out of schema migrations, batch updates by primary key, run them as resumable management commands or Celery jobs, and keep code compatible during the backfill.
- Rename a Django Model Field Without Downtime
Rename a Django model field or column without breaking running code during rolling deploys: use db_column to rename in Python only, or expand and contract with a new column, dual writes, backfill, and removal across several releases.
- Remove a Django Field Without Downtime
Drop a Django model field and its database column safely during rolling deploys: stop using the field in code first, remove it from Django’s state with SeparateDatabaseAndState, drop the column in a later release, and handle NOT NULL columns and dependent indexes.
- Migrate a Django Integer Primary Key to BigInt Without Downtime
Convert a Django AutoField primary key to BigAutoField before it overflows: estimate time to exhaustion, avoid the table-rewriting ALTER on big tables, add a new bigint column with triggers, backfill, swap keys and foreign keys, and handle sequences.
Check it
Review lists to run before launch or after a change.
- Django Migration Review Checklist
A code-review checklist for Django migrations before they reach production: backward compatibility with running code, locking and table rewrites, large-table operations, data migrations, reversibility, dependencies, and deployment order.
Fix it
Errors and symptoms, each traced to a cause and a fix.
- Django Migration Failed During Deploy: Recovery Playbook
A failed Django migration during deploy usually means your release reached production, but the database change step did not finish cleanly.
- Fix InconsistentMigrationHistory in Django
Fix Django InconsistentMigrationHistory errors safely: read the dependency message, compare history with files, handle custom user models, avoid data loss.
- Fix Django Migrations Hanging on a Database Lock
Fix a Django migrate command that hangs during deploy: find the blocking PostgreSQL session with pg_blocking_pids, stop the lock queue from taking the site down, and set lock_timeout.
- Fix "relation does not exist" in Django Production
Fix ProgrammingError: relation does not exist (and SQLite 'no such table') in Django production: unapplied or uncommitted migrations, the wrong database, faked migrations, and import-time queries.
- Fix "Conflicting migrations detected" in Django
Fix Django's 'Conflicting migrations detected; multiple leaf nodes' error: merge or re-parent migrations in development, handle already-applied branches, and block conflicts in CI before deploy.
- Fix "You have unapplied migrations" in Production
Fix the Django warning You have N unapplied migration(s) on a production server: run migrate in the deploy pipeline, check which migrations are pending, handle migrations missing from the repo, and stop the warning from hiding real problems.
- Fix "relation already exists" When Running Django Migrations
Fix Django migrate failing with relation already exists, table already exists, or DuplicateTable: compare the schema with migration history, use migrate --fake or --fake-initial correctly, and avoid faking migrations that were never applied.
- Fix Django models.W042 Auto-Created Primary Key Warning
Fix the Django models.W042 warning about auto-created primary keys: choose between AutoField and BigAutoField for DEFAULT_AUTO_FIELD, avoid surprise migrations on large tables, handle third-party apps, and prepare for the BigAutoField default in Django 6.0.
- Fix Django Migration "Column Contains Null Values"
Fix the Django migration error column contains null values when adding a non-nullable field or changing null=True to null=False: backfill data first, split the change into safe migrations, and keep deploys working on large PostgreSQL tables.
- Fix Django NodeNotFoundError: Migration Dependencies Reference Nonexistent Parent Node
Fix the Django NodeNotFoundError saying migration dependencies reference a nonexistent parent node: restore deleted or uncommitted migration files, repair dependencies after squashing or renaming apps, and handle third-party app version mismatches.
- Fix Django LookupError: No Installed App With Label
Fix the Django LookupError no installed app with label in production, migrations, and Celery: add the app to INSTALLED_APPS, use the right app label, load the correct settings module, and avoid model imports before Django is ready.
- Fix "AUTH_USER_MODEL Refers to Model That Has Not Been Installed"
Fix the Django ImproperlyConfigured error AUTH_USER_MODEL refers to model that has not been installed: check the app_label.ModelName format, INSTALLED_APPS, import order, and what to do when switching to a custom user model on an existing database.
- Fix "permission denied for schema public" on PostgreSQL 15+
Fix Django migrate failing with permission denied for schema public on PostgreSQL 15 and newer: make the app role own the database or schema, grant CREATE on public, and set up roles correctly on managed databases.
- Fix MySQL "Incorrect string value" With utf8mb4
Fix Django DataError 1366 Incorrect string value when saving emoji or other 4-byte characters to MySQL: convert databases, tables, and columns to utf8mb4, set the connection charset, and handle index length limits.
- Fix "value too long for type character varying" in Django
Fix Django DataError value too long for type character varying(N) on PostgreSQL: find the field and the input, raise max_length with a safe migration, validate in forms and serializers, and understand why SQLite never complained.
- Fix PostgreSQL "Database Is Being Accessed by Other Users" in Django
Fix the PostgreSQL error database is being accessed by other users when Django tests, restores, or resets drop a database: find the open sessions, stop app processes and pools, terminate backends, or use DROP DATABASE WITH (FORCE).
- Fix "Permission Denied to Create Extension" in Django Migrations
Fix the PostgreSQL error permission denied to create extension when Django migrations add pg_trgm, unaccent, hstore, citext, or PostGIS: create extensions as an admin once, use trusted extensions, and handle RDS, Cloud SQL, Azure, and Supabase.
- Fix MySQL "Specified Key Was Too Long" in Django Migrations
Fix the MySQL error 1071 Specified key was too long; max key length is 767 or 3072 bytes in Django migrations: understand utf8mb4 index limits, use InnoDB DYNAMIC rows, shorten indexed CharFields, or index a prefix.