# 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.