# Django + Neon: the three settings that matter
## The trap
Django defaults keep database connections open across requests (`CONN_MAX_AGE`), and Neon closes idle connections after 5 minutes. The result is intermittent "connection already closed" errors that only happen on quiet apps, the hardest kind to reproduce. Separately, Django's server-side cursors assume session state that PgBouncer transaction mode does not preserve.
## The rule (from Neon's Django guide)
```python
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": getenv("PGDATABASE"),
"USER": getenv("PGUSER"),
"PASSWORD": getenv("PGPASSWORD"),
"HOST": getenv("PGHOST"),
"PORT": getenv("PGPORT", 5432),
"OPTIONS": {"sslmode": "require"},
"DISABLE_SERVER_SIDE_CURSORS": True,
"CONN_HEALTH_CHECKS": True,
}
}
```
- `CONN_MAX_AGE = 0` (the default): close connections at the end of each request so Django never reuses one Neon already closed. On Django 4.1+ you can use a higher `CONN_MAX_AGE` combined with `CONN_HEALTH_CHECKS` for reuse with safety.
- `DISABLE_SERVER_SIDE_CURSORS = True`: required with the pooler.
- `OPTIONS: {sslmode: require}`: Neon requires SSL.
## Checklist
- Start with `CONN_MAX_AGE = 0`; only raise it with `CONN_HEALTH_CHECKS = True` on 4.1+.
- Pooled connection string for the app; direct for `migrate`.
- If you see cursor errors only under the pooler, this setting is the first thing to check.