Skip to main content

Multi-Database Migrations

Django-CFG provides two powerful commands for managing multi-database migrations.

migrate_all (Production)

Automatically migrates all databases based on routing configuration.

Usage

# Migrate all databases
python manage.py migrate_all

# Skip automatic makemigrations
python manage.py migrate_all --skip-makemigrations

Features

  • ✅ Auto-detects all databases from settings
  • ✅ Creates migrations first (unless --skip-makemigrations)
  • ✅ Migrates each database based on routing rules
  • ✅ Handles constance app automatically
  • ✅ Shows success/failure for each database

Example Output

$ python manage.py migrate_all

🚀 Migrating all databases...

🔄 Migrating database: default
📦 Migrating all apps...
✅ Migrations completed for default

🔄 Migrating database: blog_db
📦 Migrating app: blog
✅ Migrations completed for blog_db

🔄 Migrating database: shop_db
📦 Migrating app: shop
✅ Migrations completed for shop_db

✅ All migrations completed successfully

When to Use

Production deployments:

# CI/CD pipeline
python manage.py migrate_all

Docker entrypoint:

CMD python manage.py migrate_all && gunicorn

migrator (Development)

Interactive migration tool with auto mode and targeted migrations.

Usage

# Auto mode - migrates all databases without prompts
python manage.py migrator --auto

# Interactive mode - shows menu
python manage.py migrator

# Migrate specific database
python manage.py migrator --database blog_db

# Migrate specific app
python manage.py migrator --app blog

# Migrate specific app on specific database
python manage.py migrator --database blog_db --app blog

Interactive Mode

When run without --auto, shows an interactive menu:

🗄️  Django Database Migrator
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📋 Current Configuration:
Databases: default, blog_db, shop_db
Apps: accounts, blog, shop, profiles

What would you like to do?
> Migrate all databases (recommended)
Migrate specific database
Show database status
View configuration info
Exit

Auto Mode

Runs automatic migration without prompts:

$ python manage.py migrator --auto

🚀 Running automatic migration...

📦 Creating migrations for all apps...
✅ Migrations created successfully

🔄 Migrating database: default
📦 Migrating all apps...
✅ Migrations completed for default

🔄 Migrating database: blog_db
📦 Migrating app: blog
✅ Migrations completed for blog_db

🔄 Migrating database: shop_db
📦 Migrating app: shop
✅ Migrations completed for shop_db

✅ Constance migrated successfully

Migration Flow

  1. Creates migrations - Runs makemigrations for all apps
  2. Migrates default database - Migrates main database first
  3. Migrates routed databases - Migrates blog_db, shop_db based on routing rules
  4. Migrates constance - Always migrates constance app (required by django-cfg)

When to Use

Development:

# Quick migration during development
python manage.py migrator --auto

Testing specific database:

# Test blog database migrations only
python manage.py migrator --database blog_db

Troubleshooting:

# Interactive mode to explore database status
python manage.py migrator
# Select "Show database status" from menu

Comparison

Featuremigrate_allmigrator --auto
Interactive menu❌ No✅ Yes (without --auto)
Auto makemigrations✅ Yes (unless --skip-makemigrations)✅ Yes
Respects routing rules✅ Yes✅ Yes
Specific database❌ Migrates all✅ --database flag
Specific app❌ Migrates all apps✅ --app flag
Constance handling✅ Automatic✅ Automatic
Best forProduction, CI/CDDevelopment, targeted migrations

Standard Django Migrations

You can still use standard Django migration commands:

# Create migrations
python manage.py makemigrations
python manage.py makemigrations blog

# Migrate specific database
python manage.py migrate --database=blog_db
python manage.py migrate blog --database=blog_db

# Migrate all databases (respects routing)
python manage.py migrate

# Show migration status
python manage.py showmigrations
python manage.py showmigrations --database=blog_db

# Fake migration
python manage.py migrate --fake blog_db

# Rollback migration
python manage.py migrate blog 0001

Migration Strategies

Initial Setup

# 1. Create migrations
python manage.py makemigrations

# 2. Migrate all databases
python manage.py migrate_all

# 3. Verify
python manage.py showmigrations

Adding New Model

# 1. Add model to apps/blog/models.py
# 2. Create migration
python manage.py makemigrations blog

# 3. Migrate blog database only
python manage.py migrator --database blog_db

Production Deployment

# Pre-deployment check
python manage.py migrate_all --dry-run

# Deploy migrations
python manage.py migrate_all

# Verify
python manage.py showmigrations

Routing and Migrations

How Routing Affects Migrations

# settings.py
DATABASE_ROUTING_RULES = {
'blog': 'blog_db',
'shop': 'shop_db',
}

Migration behavior:

  • Blog app migrations → run on blog_db only
  • Shop app migrations → run on shop_db only
  • Other apps → run on default database

Migration Storage

Migrations are tracked in the django_migrations table in each database:

# Check migrations on specific database
python manage.py dbshell --database=blog_db
SELECT * FROM django_migrations WHERE app = 'blog';

Troubleshooting

Migration Already Applied

# Fake the migration
python manage.py migrate --fake blog 0001 --database=blog_db

Migration Conflicts

# Check for conflicts
python manage.py makemigrations --check

# Merge migrations
python manage.py makemigrations --merge

Reset Migrations (Development Only)

# Delete migration files (keep __init__.py)
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc" -delete

# Drop and recreate databases
python manage.py migrate_all --fake-initial

Cross-Database Migration Errors

If you get relation does not exist errors:

# models.py - Add db_constraint=False for cross-database ForeignKeys
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
db_constraint=False # REQUIRED for cross-database FK
)

See: Cross-Database Relations

Best Practices

1. Always Create Migrations First

# ✅ Good
python manage.py makemigrations
python manage.py migrate_all

# ❌ Bad
python manage.py migrate_all # May fail if migrations don't exist

2. Test Migrations Locally

# Test before production
python manage.py migrate_all --dry-run

3. Use migrate_all in CI/CD

# .github/workflows/deploy.yml
- name: Run migrations
run: python manage.py migrate_all

4. Keep Migration History Clean

# Squash migrations periodically
python manage.py squashmigrations blog 0001 0010

See Also