Database configuration: DATABASES dict, connection pooling, read replicas. Use when: configuring PostgreSQL, setting up connection pooling, adding read replicas, optimizing DB settings.
CONN_MAX_AGE = 600 in production for connection reuseCONN_MAX_AGE = 0 in development for clean connectionsconn_health_checks = True (Django 4.1+) to verify connectionsappdb (dev default)# app/settings_dev.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "appdb",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "localhost",
"PORT": "5432",
"CONN_MAX_AGE": 0, # Close after each request in dev
"OPTIONS": {
"connect_timeout": 5,
},
}
}
# app/settings_production.py
import os
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ.get("DB_PORT", "5432"),
"CONN_MAX_AGE": 600, # Reuse connections for 10 min
"CONN_HEALTH_CHECKS": True, # Verify connections before use
"OPTIONS": {
"connect_timeout": 5,
"options": "-c statement_timeout=30000", # 30s query timeout
},
}
}
import dj_database_url
DATABASES = {
"default": dj_database_url.config(
default="postgresql://postgres:postgres@localhost:5432/appdb",
conn_max_age=600,
conn_health_checks=True,
)
}
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_NAME"],
# ... primary config
},
"replica": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_REPLICA_NAME"],
"HOST": os.environ["DB_REPLICA_HOST"],
# ... replica config
"CONN_MAX_AGE": 600,
"TEST": {"MIRROR": "default"}, # Use default in tests
},
}
# Database router
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints): # type: ignore[no-untyped-def]
return "replica"
def db_for_write(self, model, **hints): # type: ignore[no-untyped-def]
return "default"
def allow_relation(self, obj1, obj2, **hints): # type: ignore[no-untyped-def]
return True
def allow_migrate(self, db, app_label, model_name=None, **hints): # type: ignore[no-untyped-def]
return db == "default"
DATABASE_ROUTERS = ["app.routers.PrimaryReplicaRouter"]
# conftest.py or settings_test.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "test_appdb",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "localhost",
"PORT": "5432",
"TEST": {
"NAME": "test_appdb", # Explicit test DB name
},
}
}
| Setting | Dev | Production | Notes |
|---|---|---|---|
CONN_MAX_AGE | 0 | 600 | Seconds to keep connection open |
CONN_HEALTH_CHECKS | False | True | Verify before reuse |
connect_timeout | 5 | 5 | Seconds to establish connection |
statement_timeout | None | 30000 | Max query time (ms) |
CONN_MAX_AGE = None (infinite) — stale connectionsCONN_HEALTH_CHECKS in productionCONN_MAX_AGE = 0 in production — connection overhead on every requestconnect_timeout — queries hang indefinitely on connection failure& .\.venv\Scripts\python.exe -m ruff check . --fix
& .\.venv\Scripts\python.exe -m ruff format .
& .\.venv\Scripts\python.exe manage.py check --settings=app.settings_dev
app/settings.py — base database config.claude/rules/connection-pooling.md — pooling rules