Neon Local is a proxy service that creates a local interface to your Neon cloud database. It supports two main use cases:
- Connecting to existing Neon branches - Connect your app to any existing branch in your Neon project
- Connecting to ephemeral Neon branches - Connect your app to a new ephemeral database branch that is instantly created when the Neon Local container starts and deleted them when the container stops
Your application connects to a local Postgres endpoint, while Neon Local handles routing and authentication to the correct project and branch. This removes the need to update connection strings when working across database branches.
See our documentation for more configuration options: Neon Local Documentation
To connect to an existing Neon branch, provide the BRANCH_ID environment variable to the container. This allows you to work with a specific branch without creating a new one.
docker run \
--name db \
-p 5432:5432 \
-e NEON_API_KEY=<your_neon_api_key> \
-e NEON_PROJECT_ID=<your_neon_project_id> \
-e BRANCH_ID=<your_branch_id> \
neondatabase/neon_local:latestdb:
image: neondatabase/neon_local:latest
ports:
- '5432:5432'
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}
BRANCH_ID: ${BRANCH_ID}To create ephemeral branches (default behavior), provide the PARENT_BRANCH_ID environment variable instead of BRANCH_ID. The Neon Local container automatically creates a new ephemeral branch of your database when the container starts, and deletes it when the container stops. This ensures that each time you deploy your app via Docker Compose, you have a fresh copy of your database — without needing manual cleanup or orchestration scripts. Your database branch lifecycle is tied directly to your Docker environment.
docker run \
--name db \
-p 5432:5432 \
-e NEON_API_KEY=<your_neon_api_key> \
-e NEON_PROJECT_ID=<your_neon_project_id> \
-e PARENT_BRANCH_ID=<parent_branch_id> \
neondatabase/neon_local:latestdb:
image: neondatabase/neon_local:latest
ports:
- '5432:5432'
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}
PARENT_BRANCH_ID: ${PARENT_BRANCH_ID}If you prefer to persist ephemeral database branches across test runs, you can disable automatic branch deletion and mount your project's Git metadata into the container. Neon Local will automatically create a new Neon database branch corresponding to each Git branch you work on.
Using the Neon Local container in your CI pipeline allows you to instantly create and connect to fresh copies of your staging or test database with a simple docker compose up command — no additional automation (like GitHub Actions) required.
Run the Neon Local container using the following docker run command:
docker run \
--name db \
-p 5432:5432 \
-e NEON_API_KEY=<your_neon_api_key> \
-e NEON_PROJECT_ID=<your_neon_project_id> \
neondatabase/neon_local:latestAdd Neon Local to your docker-compose.yml:
db:
image: neondatabase/neon_local:latest
ports:
- '5432:5432'
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}The Neon Local container now supports both the postgres and Neon serverless drivers simultaneously through a single connection string. You no longer need to specify a driver or configure different connection strings for different drivers.
Connect to Neon Local using a standard Postgres connection string.
postgres://neon:npg@localhost:5432/<database_name>?sslmode=no-verifypostgres://neon:npg@db:5432/<database_name>?sslmode=no-verifyConnect using the Neon serverless driver. The Neon serverless driver requires specific configuration to work with the local proxy.
The following neonConfig settings are required for the serverless driver to work with Neon Local:
import { neon, neonConfig } from '@neondatabase/serverless';
import ws from 'ws'; // Only needed for WebSocket mode
// HTTP Mode (recommended for most applications)
neonConfig.fetchEndpoint = 'http://localhost:5432/sql'; // Routes HTTP requests to local proxy
neonConfig.poolQueryViaFetch = true; // Enables HTTP connection pooling
// WebSocket Mode (for real-time applications)
neonConfig.webSocketConstructor = ws; // Enables WebSocket support
neonConfig.useSecureWebSocket = false; // Local proxy doesn't use SSL
neonConfig.wsProxy = (host, port) => 'localhost:5432'; // Routes WebSocket connections to local proxy
neonConfig.pipelineConnect = false; // Required for authentication to work
const sql = neon('postgres://neon:npg@localhost:5432/<database_name>');fetchEndpoint: Redirects HTTP requests from Neon's cloud endpoint to your local proxyuseSecureWebSocket: false: The local proxy runs without SSL encryption for simplicitywsProxy: Intercepts WebSocket connections and routes them to the local proxy instead of Neon's cloudpipelineConnect: false: Disables connection pipelining which can interfere with proxy authentication
import { neon, neonConfig } from '@neondatabase/serverless';
// HTTP Mode (simple setup)
neonConfig.fetchEndpoint = 'http://localhost:5432/sql';
const sql = neon('postgres://neon:npg@localhost:5432/<database_name>');import { neon, neonConfig } from '@neondatabase/serverless';
// Use service name instead of localhost
neonConfig.fetchEndpoint = 'http://db:5432/sql';
const sql = neon('postgres://neon:npg@db:5432/<database_name>');For applications requiring real-time features or persistent connections:
import { neon, neonConfig } from '@neondatabase/serverless';
import ws from 'ws';
// Configure for WebSocket mode
neonConfig.webSocketConstructor = ws;
neonConfig.useSecureWebSocket = false;
neonConfig.wsProxy = (host, port) => 'localhost:5432';
neonConfig.pipelineConnect = false;
// Remove HTTP configuration
delete neonConfig.fetchEndpoint;
neonConfig.poolQueryViaFetch = false;
const sql = neon('postgres://neon:npg@localhost:5432/<database_name>');No additional environment variables are needed - the same Docker configuration works for both drivers:
docker run \
--name db \
-p 5432:5432 \
-e NEON_API_KEY=<your_neon_api_key> \
-e NEON_PROJECT_ID=<your_neon_project_id> \
neondatabase/neon_local:latest| Variable | Description | Required | Default |
|---|---|---|---|
NEON_API_KEY |
Your Neon API key. Manage API Keys | Yes | N/A |
NEON_PROJECT_ID |
Your Neon project ID. Found under Project Settings → General in the Neon console. | Yes | N/A |
BRANCH_ID |
Connect to an existing Neon branch. Mutually exclusive with PARENT_BRANCH_ID. |
No | N/A |
PARENT_BRANCH_ID |
Create ephemeral branch from parent. Mutually exclusive with BRANCH_ID. |
No | your project's default branch |
DRIVER |
Deprecated - Both drivers now supported simultaneously. | No | N/A |
DELETE_BRANCH |
Set to false to persist branches after container shutdown. |
No | true |
To persist a branch per Git branch, add the following volume mounts:
db:
image: neondatabase/neon_local:latest
ports:
- '5432:5432'
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}
volumes:
- ./.neon_local/:/tmp/.neon_local
- ./.git/HEAD:/tmp/.git/HEAD:ro,consistentNote: This will create a .neon_local directory in your project to store metadata.
Be sure to add .neon_local/ to your .gitignore to avoid committing database information.
If using Docker Desktop for Mac, ensure that your VM settings use gRPC FUSE instead of VirtioFS.
There is currently a known bug with VirtioFS that prevents proper branch detection and live updates inside containers.
