← all posts
how-to · from the raid

Getting Your Neon Database Connection String Right

Find your Neon connection string in 4 steps and pick pooled vs direct right — 1 mistake causes most errors. Ringtail wires it into your env, value-free.

Shai Snir
neon connection stringneonpostgresdatabasehow to

The Neon console Connection Details panel showing a pooled neon connection string for a Postgres database with sslmode required

Rocco copied the pooled string for the app and the direct one for migrations. Two strings, two jobs, zero 3am pages.

Rocco, the Ringtail bandit raccoon

🦝 Rocco: pooled for the app, direct for migrations. copy the wrong one and your migration just... hangs.

Your Neon connection string is in the Neon console under your project's Connection Details (or Dashboard → Connect). It looks like postgresql://user:password@ep-name-pooler.region.aws.neon.tech/dbname?sslmode=require. The most common mistake is pooled vs direct: use the pooled endpoint (host contains -pooler) for your app, and the direct endpoint for migrations. Below is where to find it, how to pick the right one, and how Ringtail wires the connection string into your env — value-free, so the credentials never touch your coding agent.

Where do you find the Neon connection string?

You find it in the Neon console under your project's Connection Details panel (some views label it Connect). Select the branch, database, and role at the top of the panel, and Neon assembles the exact connection string for that combination — copy it with the copy button rather than typing it.

Neon shows a dropdown to switch between Pooled connection and Direct connection, and toggles for the connection format (a full URI, or split PGHOST/PGUSER/etc.). For most apps you want the pooled URI. Store it as DATABASE_URL in .env.local, never committed — a database URL contains the password inline.

What are the steps to get it?

Four steps:

  1. Open the Neon console and select your project.
  2. Open Connection Details (or Dashboard → Connect).
  3. Choose the branch, database, and role, then select Pooled connection for app use.
  4. Click copy, and paste the string into .env.local as DATABASE_URL.

Because the string embeds the password, treat it like any other secret — if it lands in a commit, rotate the role's password in Neon and scrub the history, exactly as in stop committing secrets to git.

Pooled vs direct: which connection string do you use?

Use the pooled connection for your application and the direct connection for migrations and admin tasks. This one choice causes most Neon connection errors, so it's worth getting right:

  • Pooled (host contains -pooler, e.g. ep-cool-name-pooler.region.aws.neon.tech): routes through Neon's PgBouncer connection pooler. Serverless and edge functions open and close many short-lived connections, and the pooler keeps you under Postgres's connection limit. Use this for your app's DATABASE_URL.
  • Direct (host without -pooler): a direct connection to the Postgres compute. Schema migrations, some extensions, and session-level features (like LISTEN/NOTIFY or advisory locks) need a direct connection because PgBouncer's transaction pooling doesn't support them.

A migration tool pointed at the pooled endpoint can hang or error on statements the pooler won't proxy; an app pointed only at the direct endpoint can exhaust connections under load. Many stacks keep both — DATABASE_URL (pooled) for the app and DIRECT_URL (direct) for the ORM's migration command.

Rocco, the Ringtail bandit raccoon

🦝 Rocco: two endpoints, two variables. the app never runs out of connections, the migration never hangs.

How do you use it and keep SSL on?

Keep ?sslmode=require — Neon requires TLS, and dropping the parameter breaks the connection. A typical Prisma or Drizzle setup reads both variables:

# .env.local
DATABASE_URL="postgresql://user:pass@ep-name-pooler.region.aws.neon.tech/dbname?sslmode=require"
DIRECT_URL="postgresql://user:pass@ep-name.region.aws.neon.tech/dbname?sslmode=require"
// drizzle.config.ts / prisma schema
// app queries use DATABASE_URL (pooled); migrations use DIRECT_URL (direct)

Read both from the environment, never inline them. When you rotate the role's password, update both strings together so the app and migrations don't drift — the make-before-break order in rotating API keys without breaking production applies to database credentials too.

How does Ringtail wire the connection string for you?

Once you've connected your Neon account to Ringtail one time, Ringtail assembles the right connection strings for you by driving Neon's official API — the pooled URI for DATABASE_URL, the direct URI for DIRECT_URL — so you never copy the wrong endpoint again. Ringtail reads those variable names from your .env.example, calls Neon's official API for the correct endpoint host and credentials, validates that the connection opens, and writes the values into .env.local and your Infisical.

It's value-free: the credentials come from Neon's API straight into your local files. Your coding agent decides pooled vs direct per variable, but never sees the password embedded in the string. Install it once:

curl -fsSL ringtail.sh | sh
ringtail up

Ringtail uses official provider APIs only — never a browser bot with your Neon login. For provisioning every credential in a project this way, see how to stop juggling 15 API keys on every new project and store them cleanly with Infisical.

FAQ

Where do I find my Neon connection string?

Open the Neon console, select your project, and open Connection Details (or Dashboard → Connect). Choose the branch, database, and role, then copy the assembled string — it looks like postgresql://user:pass@ep-name-pooler.region.aws.neon.tech/dbname?sslmode=require. Use the copy button rather than typing it, since the string embeds the password and a typo breaks the connection.

Should I use the pooled or direct Neon connection string?

Use the pooled connection (host contains -pooler) for your application, especially serverless or edge functions, because it routes through Neon's connection pooler and keeps you under Postgres's connection limit. Use the direct connection for schema migrations and session-level features the pooler doesn't support. Many stacks set DATABASE_URL to the pooled string and DIRECT_URL to the direct string.

Why does my Neon migration hang or error?

A common cause is running migrations against the pooled endpoint. Neon's pooler uses transaction pooling, which doesn't support some statements and session-level features that migrations rely on. Point your migration command at the direct connection string (the host without -pooler) while keeping the pooled string for your app's runtime queries.

Can Ringtail set up my Neon connection string for me?

Yes. After you connect your Neon account to Ringtail once, Ringtail uses Neon's official API to assemble the correct pooled and direct connection strings, validates that they connect, and writes them to .env.local and Infisical — value-free, so the embedded password never reaches your coding agent. It uses the official API only, never browser automation.

Rocco, the Ringtail bandit raccoon
that's the whole thing. want me to mint your keys like this — value-free, one allow per provider? i self-host in one command.