Neon separates storage from compute: branches are cheap copy-on-write metadata, and idle
compute scales to zero. Wire protocol is plain Postgres — `drivers.store.sql` stays
`postgres`.

<Callout title="The one rule">
  Copy the connection string from Neon's **Connect** widget. Prefer the pooled hostname for app
  traffic and the direct hostname for migrations — never invent the `-pooler` suffix by hand.
</Callout>

## Find credentials (current console)

1. Open [console.neon.tech](https://console.neon.tech) → your **project**.
2. On the **Project Dashboard**, click **Connect**.
3. In **Connect to your database**, pick **Branch**, **Compute**, **Database**, and
   **Role**.
4. Toggle **Connection pooling** **on** for the pooled string (hostname gains `-pooler`),
   or **off** for the direct string.
5. Copy the connection string into `DATABASE_URL` (add `?sslmode=require` if missing).

```bash title="process env"
# Runtime (pooled) — ep-….…-pooler.…neon.tech
DATABASE_URL=postgresql://neondb_owner:…@ep-xxxx-pooler.region.aws.neon.tech/neondb?sslmode=require

# Migrations / pg_dump / LISTEN — same host without -pooler
# OKE_STORE_SQL_URL=postgresql://neondb_owner:…@ep-xxxx.region.aws.neon.tech/neondb?sslmode=require
```

No `images["store.sql"]` pin — Neon runs the server.

## Pooled vs direct

| Use                                                           | Which string              | Why                                                      |
| ------------------------------------------------------------- | ------------------------- | -------------------------------------------------------- |
| App / serverless / Drizzle runtime                            | **Pooled** (`-pooler`)    | PgBouncer transaction mode; up to 10k client connections |
| `oke db migrate` / `pg_dump` / logical replication / `LISTEN` | **Direct** (no `-pooler`) | Session features break under transaction pooling         |

Do **not** also put [PgDog](/docs/recipes/pgdog) in front of Neon — one pooler only.

**Consequence:** seeding or migrations through the pooled URL often fail with prepared-statement
errors; switch those jobs to the direct URL.

## pgvector and roles

`CREATE EXTENSION vector;` works on every plan — no add-on. Roles created in the Neon
Console / CLI / API get `neon_superuser` membership and can install supported extensions.

Roles you create only with raw SQL (`CREATE ROLE`) do **not** get `neon_superuser` — they
hit permission errors on extension install. Create app roles in the Console (or grant
deliberately) when you need `pgvector` setup from that role.

## Free tier / production limits

| Limit         | Free plan                                 |
| ------------- | ----------------------------------------- |
| Scale to zero | After **5 min** idle — **cannot disable** |
| Compute       | **100 CU-hours** / project / month        |
| Storage       | **0.5 GB** / project                      |
| Autoscaling   | Up to 2 CU                                |

Hitting CU-hours or storage **suspends compute** until the next billing period or an
upgrade. Always-on production needs Launch/Scale with scale-to-zero disabled.

## Query performance

<Callout title="Create the extension — do not set command">
  Neon already preloads `pg_stat_statements`. `CREATE EXTENSION` is enough. There is no oke
  `command` overlay and no `online_advisor` shim.
</Callout>

| Step    | What you do                                         |
| ------- | --------------------------------------------------- |
| Preload | Neon compute (already on)                           |
| Create  | `CREATE EXTENSION IF NOT EXISTS pg_stat_statements` |
| Console | Store → SQL band → **Performance**                  |

Scale-to-zero **wipes** statement stats when compute sleeps. Index Advisor is
not in the default Neon catalog — Performance shows a CTA, not a failing Enable.

## Real gotcha — cold start

After scale-to-zero, the first query pays a wake-up (hundreds of ms to a few seconds).
Health checks that expect sub-100ms on an idle Free project will flap. Paid plans can
disable scale-to-zero; Free cannot.

## Troubleshooting

<Accordions>
<Accordion title="remaining connection slots are reserved / pooler wait timeout">

Too many **direct** connections, or pooler server pool exhausted for your compute size.
Move runtime traffic to the `-pooler` hostname; keep a small number of direct admin
sessions. Neon reserves connections for the superuser account on each compute size.

</Accordion>
<Accordion title="Performance KPIs reset after idle">

Free (and any scale-to-zero) compute drops `pg_stat_statements` memory when the
endpoint sleeps. Re-run traffic after wake — this is not a Console bug.

</Accordion>
<Accordion title='permission denied to create extension "vector"'>

The role is not a Console-created / `neon_superuser` member. Re-run as `neondb_owner` (or
another Console role), or grant appropriately — raw SQL roles start with public-schema
privileges only.

</Accordion>
</Accordions>

## Learn more

- [Postgres (image)](/docs/recipes/postgres) — self-hosted peer
- [Store · Index](/docs/elements/store#index) — `pgvector` usage
- [PgDog](/docs/recipes/pgdog) — when you self-host pooling instead

## Next

<Cards>
  <Card
    title="Supabase"
    description="Another managed Postgres option."
    href="/docs/providers/supabase"
  />
  <Card
    title="CockroachDB"
    description="Distributed SQL alternative."
    href="/docs/providers/cockroachdb"
  />
  <Card title="PgDog" description="Self-hosted pooler comparison." href="/docs/recipes/pgdog" />
</Cards>
