Data API
buildingTwo connection strings, which one to use, and the settings that matter.
Connecting
You get two connection strings. They reach the same database.
postgresql://booking_owner:…@ep-little-morning-b130w8eo-pooler.c-5.eu-central-1.aws.neon.tech/booking?sslmode=require&channel_binding=require
postgresql://booking_owner:…@ep-little-morning-b130w8eo.c-5.eu-central-1.aws.neon.tech/booking?sslmode=require&channel_binding=require| Use it for | |
|---|---|
Pooled (-pooler) | Your application. Anything serverless, edge, or with many short-lived connections |
| Direct | Migrations, psql, and anything holding one long connection |
Why two
Postgres allocates a process per connection, and a small compute allows a few
hundred. A serverless application opens one per invocation, so a traffic spike
becomes too many clients already at exactly the moment you least want it.
The pooled endpoint puts PgBouncer in front, so thousands of client connections
share a few real ones. The cost is that it is in transaction pooling mode:
session-level state does not survive between statements. In practice that means
LISTEN/NOTIFY, advisory locks held across statements, and some migration
tools do not work through it — which is what the direct endpoint is for.
Use pooled unless something breaks. Then use direct for that one thing.
Examples
1import { Pool } from "pg";2 3const pool = new Pool({ connectionString: process.env.DATABASE_URL });4const { rows } = await pool.query("select now()");1import postgres from "postgres";2 3const sql = postgres(process.env.DATABASE_URL);4const rows = await sql`select now()`;1psql "$DATABASE_URL_DIRECT"Any Postgres client works — this is not an API of ours with a driver to learn.
Prisma, Drizzle, Sequelize, SQLAlchemy, ActiveRecord and psql all connect to it
the way they connect to any Postgres.
On a runtime with no TCP sockets — Cloudflare Workers, some edge functions — use
a driver that speaks Postgres over HTTP. @neondatabase/serverless is the one
that matches the host below, and it takes the same connection string.
Who runs the machine
The hostname says neon.tech, and rather than dress that up: the Postgres
underneath is Neon, resold by us. We create it, set its limits, meter it and
put it on your bill; they run the hardware. It is listed among our
subprocessors with everyone else.
Worth knowing because of what it means for you rather than for us:
- It is not a fork. Standard Postgres 18, standard extensions, standard wire protocol. Nothing here is a dialect you would have to unlearn.
- You can leave.
pg_dumpagainst the direct string is a complete copy, and it restores into any Postgres anywhere. Nothing about this is a lock-in designed to be hard to undo. - Your account is with us. One invoice, one support conversation, one place that owes you an answer when a query is slow.
TLS is not optional
Both strings carry sslmode=require and channel_binding=require, and the
server refuses anything less. Do not strip them. A client that cannot do channel
binding can drop that parameter; sslmode stays.
Keep it in an environment variable
The string contains a password. It belongs in your platform's secret store, not in a repository, and it is worth reading replacing the password before the first time somebody pastes it into a chat window.