What are Django migrations, and how do you handle a migration that would lock a large table?
Migrations are versioned, ordered Python files describing schema changes. makemigrations compares your models to the existing migration state and generates the difference; migrate applies it and records the result in django_migrations.
The commands worth knowing: sqlmigrate shows the SQL a migration will run — always read it before applying anything to a large table. showmigrations lists what has been applied. --fake marks a migration applied without running it, for when the schema is already correct.
For a large table, the danger is the lock. The safe approach:
- Add columns as nullable with no default. On PostgreSQL a nullable column with no default is a metadata-only change. Adding a NOT NULL column with a default rewrites the whole table on older versions.
- Backfill in batches in a separate data migration or management command, not inside the schema migration.
- Create indexes concurrently. Use
AddIndexConcurrentlyfromdjango.contrib.postgres.operationswithatomic = Falseon the migration. - Split add-and-populate into separate deploys so old and new code can both run against the schema during the rollout.
Note: Setting a lock_timeout so a migration fails fast rather than queueing behind traffic is a strong detail to mention.





