ICYMI we recently launched Neon Local.
What is Neon Local?
Neon Local is a proxy service that creates a local interface to your Neon cloud database. By default, it automatically creates a new database branch when your container starts and deletes it when the container stops. Your app connects to a local Postgres endpoint while Neon Local handles routing and authentication to the correct project and branch. This means you don’t have to update connection strings across branches.
Our docs cover how to use Neon Local with both our serverless driver and pg, but one area that might cause some confusion is how to switch between Neon Local in development and your Neon cloud database in production.
In this guide, I’ll show you how to set up your project to work in both development and production environments.
1. Example application
To demonstrate, I’ve built a simple React + Vite + Express app. It has one route (/
) that runs SELECT version()
and returns the result.
You can find the project here:
2. Setup
Environment variables
You’ll need to configure the following environment variables. They are also listed in the example application's repository README.
Variable | Description | Example / Value |
---|---|---|
DATABASE_URL | Connection string for database | (Set appropriately) |
NODE_ENV | Node environment mode | production or development |
NEON_API_KEY | Neon API authentication key | napi_6ngd23amjggx7... |
NEON_PROJECT_ID | Neon project identifier | rosty-king-89... |
PORT | Server port | 8080 |
If you need help finding up any of these variables, refer to the following resources:
Docker for Mac
This guide uses Docker for Mac. If you don’t have it installed yet, follow this guide:
3. Running the app
If you've cloned the repo, and followed the install instructions, run the app with one of the following commands:
- development:
docker compose --profile dev --env-file .env.dev up --watch
- production:
docker compose --profile prod --env-file .env.prod up --build
Once the app is running, go to http://localhost:8080/ in your browser.
4. Ephemeral branches
If you started the app in development mode, go to the Neon console, and you’ll see a new branch has been created using the main
, or production
branch as a base.
If you started the app in production mode, the app will connect to the database defined by the DATABASE_URL
, and no new branch will be created.
In the next section, we’ll look at the Docker configuration and how the app determines whether to connect to Neon Local or the cloud instance defined by DATABASE_URL
.
5. Configuration
Docker Compose
Here’s the docker-compose.yml
setup, which defines two services. The first, app
, starts the Express server, responsible for data fetching and server-side rendering of the React app. The second, db
, configures the Neon Local Docker image.
Additionally, the app
service defines two profiles, dev
and prod
. The db
service also defines a dev
profile, ensuring that the db
service is only used when the app is run in development mode.
How Docker Profiles Work
Docker profiles allow you to group services within your docker-compose.yml
file, enabling you to choose which services to start depending on the environment or use case.
- The
app
service has bothdev
andprod
profiles. This means theapp
can be run in either development or production mode. - The
db
service is only included in thedev
profile, meaning it will only run when the app is started in development mode.
services:
app:
build: .
ports:
- '${PORT}:${PORT}'
volumes:
- .:/app
- /app/node_modules
environment:
- PORT=${PORT}
- NODE_ENV=${NODE_ENV}
- DATABASE_URL=${DATABASE_URL}
- NEON_API_KEY=${NEON_API_KEY}
- NEON_PROJECT_ID=${NEON_PROJECT_ID}
profiles:
- dev
- prod
db:
image: neondatabase/neon_local:latest
ports:
- '5432:5432'
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}
DRIVER: serverless
profiles:
- dev
You can view the src
of this file in the repository: docker-compose.yml
6. Connecting to the database
Serverless Driver
The database connection is established using our serverless driver. It uses a ternary operation to determine whether to connect to Neon Local or the DATABASE_URL
, depending on the mode the application is running in.
import 'dotenv/config';
import { neon, neonConfig } from '@neondatabase/serverless';
if (process.env.NODE_ENV !== 'prod') {
neonConfig.fetchEndpoint = 'http://db:5432/sql';
}
const connectionString =
process.env.NODE_ENV === 'prod' ? process.env.DATABASE_URL : 'postgres://neon:npg@db:5432/neondb';
export const sql = neon(connectionString);
You can view the src
of this file in the repository: src/db.js:
node-postgres
Alternatively, if you prefer to use pg
, here's how the connection is configured. Note that you'll need to add ?sslmode=no-verify
to the end of the Neon Local connection string.
import 'dotenv/config';
import pg from 'pg';
const { Pool } = pg;
const connectionString =
process.env.NODE_ENV === 'prod'
? process.env.DATABASE_URL
: 'postgres://neon:npg@db:5432/neondb?sslmode=no-verify';
export const pool = new Pool({ connectionString });
Additionally, you'll also need to change the DRIVER
to postgres
in your docker-compose.yml
file:
environment:
NEON_API_KEY: ${NEON_API_KEY}
NEON_PROJECT_ID: ${NEON_PROJECT_ID}
DRIVER: serverless
DRIVER: postgres
Wrapping up
And that’s it. By default, Neon Local handles creating and deleting a branch whenever you start or stop the container. If you want more control, such as setting a parent branch or disabling branch deletion, check out the configuration options in the docs.
Neon Local simplifies the management of temporary database environments, making it easier to work with isolated instances for testing or short-term use. While it’s not a fully "local" database, it streamlines the workflow, especially for CI/CD pipelines where short-lived environments are needed to run tests but don’t need to stick around.
Neon Local is still in its early stages, with several improvements on the way. But for now, it could be exactly what you need to streamline your workflows. Give it a try today and share your feedback with us.