# CLAUDE.md: Neon Postgres

## Connections
- `DATABASE_URL` uses the pooled host (`...-pooler...neon.tech`) for the app; `DATABASE_URL_UNPOOLED` (direct) for migrations and long sessions. Both come from env, never hard-coded.
- Serverless/edge runtimes use `@neondatabase/serverless`: `neon(url)` for one-shot HTTP queries, `Pool`/`Client` over WebSockets when you need transactions or sessions.
- Long-running servers can use regular `pg`/`postgres`/`psycopg` with the pooled URL; keep pool sizes small.
- With an ORM (Drizzle `drizzle-orm/neon-http`, Prisma with the Neon adapter), follow its Neon setup instead of mixing drivers.
- Expect cold starts after scale-to-zero: set connect timeouts and one retry for the first query.

## Branches
- Never run experiments or destructive SQL on the `main`/production branch.
- Create a branch for risky work: `neonctl branches create --name <feature> --parent main`, then get its URL with `neonctl connection-string <feature>`. Delete it when done (ask first).
- Preview deployments get their own branch through the CI integration if configured.

## Migrations
- Use the repo's migration tool against the direct (unpooled) URL. Test on a branch first, then apply to main through CI.
- Follow zero-downtime rules: concurrent indexes, nullable columns first, batched backfills.

## Queries
Parameterized only. The serverless driver's tagged template (sql`...${id}...`) sends `id` as a parameter; building SQL by string concatenation does not.
