Django Migrations: Best Practices for Production
## The Golden Rules
1. **Never edit a migration after it has been applied in production**
2. **Always test migrations on a staging database first**
3. **Backup before migrating** — always
## Zero-Downtime Migrations
Avoid locking large tables. Instead of one destructive migration, use the expand/contract pattern:
**Phase 1 (deploy):** Add the new nullable column
```python
# 0042_add_column.py
operations = [
migrations.AddField('MyModel', 'new_field', models.CharField(max_length=100, null=True))
]
```
**Phase 2 (backfill):** Populate data without a migration
```bash
python manage.py shell -c "MyModel.objects.filter(new_field=None).update(new_field='default')"
```
**Phase 3 (next deploy):** Make the column NOT NULL
```python
migrations.AlterField('MyModel', 'new_field', models.CharField(max_length=100))
```
## Squashing Migrations
After many iterations, squash to keep history clean:
```bash
python manage.py squashmigrations website 0001 0020
```
## Rolling Back
```bash
python manage.py migrate website 0019 # roll back to migration 19
```
Always test rollback in staging before relying on it in production.