Django cookbook · Advanced
Add a required column without downtime
Adding a NOT NULL column (or renaming one) locks the table or breaks the running version during deploys.
Approach
Split the change across deploys so old and new code both work: add the column as nullable (or with a database default), backfill, then make it required. For renames, add the new column, write both, switch reads, then drop.
Solution
# Deploy 1: add the column with a database-level default (no table rewrite on PostgreSQL 11+)
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("shop", "0020_previous")]
operations = [
migrations.AddField(
model_name="order",
name="currency",
field=models.CharField(max_length=3, db_default="USD"),
),
]
# Deploy 2 (after backfilling any special cases): add an index without locking writes
from django.contrib.postgres.operations import AddIndexConcurrently
class Migration(migrations.Migration):
atomic = False # CONCURRENTLY can't run in a transaction
dependencies = [("shop", "0021_order_currency")]
operations = [
AddIndexConcurrently("order", models.Index(fields=["currency", "created_at"], name="order_currency_idx")),
]
Pitfalls
- Renaming a column in one step while the old code (still running during the deploy) uses the old name.
- Creating indexes on large tables without
CONCURRENTLY, blocking writes. - Removing a field from the model and the database in the same deploy; remove it from code first.
Variations
- Use
SeparateDatabaseAndStateto change Django's view of a field without touching the database. - Tools like
django-pg-zero-downtime-migrationsadd checks for unsafe operations.
Further reading: Field.db_default
Reference: https://docs.djangoproject.com/en/6.0/ref/models/fields/#db-default
More Django recipes
- Add full-text search with PostgreSQL
- Add health checks and structured logging
- Avoid N+1 queries with select_related and prefetch_related
- Cache expensive queries and invalidate on change
- Call external APIs concurrently in async views
- Configure settings from environment variables
- Enforce rules with database constraints
- Harden security settings, including a Content Security Policy