Skip to main content

Multi-Database Configuration

Automatic Database Routing

Django-CFG provides automatic database routing - no need to manually specify using() on every query. Configure once, and all queries route to the correct database automatically.

Configure multiple databases with automatic routing in Django-CFG.

Basic Multi-Database Setup

Simple Multi-Database Pattern

Perfect for small to medium projects with 2-3 databases.

# config.py
from django_cfg import DjangoConfig
from django_cfg.models import DatabaseConfig

class MyConfig(DjangoConfig):
databases = {
"default": DatabaseConfig(
engine="django.db.backends.postgresql",
name="main_db",
user="postgres",
password="${DB_PASSWORD}",
host="localhost",
),
"blog_db": DatabaseConfig(
engine="django.db.backends.postgresql",
name="blog_db",
user="postgres",
password="${DB_PASSWORD}",
host="localhost",
),
}

database_routers = ["django_cfg.routing.routers.AppDatabaseRouter"]

# Routing rules
database_routing_rules = {
"blog": "blog_db", # Blog app → blog_db
}
Simple Pattern Benefits
  • Easy to understand - Clear database definitions
  • Type-safe - Full IDE autocomplete
  • Automatic routing - No manual using() calls
  • Environment variables - Secure credential management

YAML Configuration

# config.yaml
database:
url: "postgresql://user:${DB_PASSWORD}@localhost:5432/main_db"
url_blog: "postgresql://user:${DB_PASSWORD}@localhost:5432/blog_db"
url_shop: "postgresql://user:${DB_PASSWORD}@localhost:5432/shop_db"

URL Format Examples

SQLite (Development):

database:
url: "sqlite:///db/default.sqlite3"
url_blog: "sqlite:///db/blog.sqlite3"

PostgreSQL (Production):

database:
url: "postgresql://user:pass@db-main.example.com:5432/main"
url_blog: "postgresql://user:pass@db-blog.example.com:5432/blog"

With SSL:

database:
url: "postgresql://user:pass@localhost/main?sslmode=require"

Database Routing

Django-CFG automatically routes database operations based on DATABASE_ROUTING_RULES:

# settings.py
DATABASE_ROUTING_RULES = {
'blog': 'blog_db', # All blog app models → blog_db
'shop': 'shop_db', # All shop app models → shop_db
# Apps not listed → default database
}

Automatic Routing

# models.py - apps/blog/models.py
class Post(models.Model):
title = models.CharField(max_length=200)
# No need to specify database!

# Usage - automatically routed to blog_db
Post.objects.create(title="Hello")
Post.objects.all() # Queries blog_db automatically

Cross-Database ForeignKeys

CRITICAL: db_constraint=False Required

When creating ForeignKeys to models in different databases (e.g., User in default, Post in blog_db), you MUST use db_constraint=False. This is required because database constraints cannot span multiple databases.

Implementation

# apps/blog/models.py
from django.contrib.auth import get_user_model

User = get_user_model() # Lives in 'default' database

class Post(models.Model):
title = models.CharField(max_length=200)

# Cross-database ForeignKey
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='blog_posts',
db_constraint=False # ⚠️ REQUIRED for cross-database FK
)

class Meta:
db_table = 'blog_post'

Why db_constraint=False?

Technical reasons:

  • User model is in default database
  • Post model is in blog_db database
  • Database-level foreign key constraints cannot span databases
  • Django ORM handles the relationship at application level
  • Without it: relation "auth_user" does not exist error during migrations

How it works:

  1. Django stores only the foreign key value (author_id=1)
  2. No database constraint created
  3. Relationship resolved at application level when accessed
  4. post.author triggers ORM query to default database

Migration Commands

Django-CFG provides two commands for multi-database migrations:

Automatically migrates all databases:

# Migrate all databases
python manage.py migrate_all

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

Features:

  • Auto-detects all databases
  • Creates migrations first
  • Migrates each database based on routing rules
  • Handles constance app automatically

Interactive migration tool with auto mode:

# 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

See: Core Commands for detailed migrator documentation.

Complete Production Example

# config.prod.yaml
database:
# Main database
url: "postgresql://user:${DB_PASSWORD}@db-main.example.com:5432/main?sslmode=require&connect_timeout=10"

# Domain databases
url_blog: "postgresql://user:${DB_PASSWORD}@db-blog.example.com:5432/blog?sslmode=require"
url_shop: "postgresql://user:${DB_PASSWORD}@db-shop.example.com:5432/shop?sslmode=require"

# Analytics - read-only
url_analytics: "postgresql://readonly:${DB_READONLY_PASSWORD}@warehouse.example.com:5432/analytics?sslmode=require"
# settings.py
import dj_database_url
from django_cfg import load_config

config = load_config()

DATABASES = {
'default': dj_database_url.parse(config.database.url),
'blog_db': dj_database_url.parse(config.database.url_blog),
'shop_db': dj_database_url.parse(config.database.url_shop),
'analytics': dj_database_url.parse(config.database.url_analytics),
}

DATABASE_ROUTERS = ['django_cfg.routing.DatabaseRouter']

DATABASE_ROUTING_RULES = {
'blog': 'blog_db',
'shop': 'shop_db',
'analytics': 'analytics',
}

Testing Multi-Database Setup

# Create migrations
python manage.py makemigrations

# Migrate all databases
python manage.py migrate_all

# Or use migrator in auto mode
python manage.py migrator --auto

# Test routing in shell
python manage.py shell
# Shell - test automatic routing
from apps.blog.models import Post
from django.contrib.auth import get_user_model

User = get_user_model()

# Create user in default database
user = User.objects.create_user(username='john', email='john@example.com')

# Create post in blog_db with cross-database FK
post = Post.objects.create(
title='Hello World',
content='Multi-database setup works!',
author=user # Cross-database FK
)

# Test relationships
print(post.author.username) # 'john'
print(user.blog_posts.all()) # QuerySet with post

See Also

Database Configuration

Core Database Setup:

Infrastructure:

Configuration & Setup

Getting Started:

Production:

Examples & Guides

Practical Examples:

Related Guides:

Tools & Operations

CLI & Management:

Background Processing:

Note: All examples use YAML-based configuration via env loader. See Configuration Guide for setup.