Switching to Netlify Database means adopting the workflow opinions that come with it — especially that migrations drive your schema and deploys drive your cutover. This guide describes the shape of the switch; the exact commands you run depend on your source database and your application stack.
This guide covers switching from any Postgres source — an external Neon account, Supabase, RDS, a self-managed instance, or the legacy Neon extension (@netlify/neon). Where the legacy extension differs, we call it out inline.
Why switch?
Section titled “Why switch?”The new Netlify Database experience offers:
- Branches that mirror production, on demand. Every deploy preview gets its own database branch forked from production data — there’s no staging database to keep in sync.
- Schema and code ship together. Migrations apply at the right point in the deploy lifecycle, so the database never falls out of step with the application that depends on it.
- Safe collaboration by default. Production is shielded from previews and agent runs, so experimentation can’t corrupt live data.
- Native to the platform. Provisioning, connection strings, credentials, and branches are all part of your Netlify project — no separate dashboard or out-of-band keys.
- Built for AI agents. Branches provide isolated environments for previewing database changes before publishing to production. When you use Agent Runners to make database changes, only someone on your team with the right permissions can publish to production. When you work with Netlify Database locally this setup can still reduce the likelihood of an AI agent accessing your production database.
The approach
Section titled “The approach”The switch follows the same opinions as the rest of Netlify Database:
- Migrations drive your schema. Even if your current database was managed outside of a migration workflow, you’re adopting one now.
- Preview branches rehearse production changes. You’ll prove the full cutover on a preview deploy before touching production.
- Deploys drive the cutover. Production moves when a deploy ships.
- Rollback is always a revert. Each phase is independently reversible.
The switch happens across three phases. Your source database keeps serving production traffic until the final phase, so you can abandon or roll back at any earlier point without user-visible impact.
Prerequisites
Section titled “Prerequisites”- A linked Netlify project currently serving from an existing Postgres database
- The latest version of Netlify CLI installed and authenticated
pg_dumpandpg_restoreavailable locally, with versions that match your source server- Recommended: install the
netlify-databaseskill into your coding agent — see Netlify Skills
Phase 1 — Provision the new database
Section titled “Phase 1 — Provision the new database”The goal of Phase 1 is to bring Netlify Database online alongside your source database, without changing any application code. When this phase is done, the new database exists and has your schema, but no traffic is hitting it yet.
On a new branch:
-
Run
netlify database initto install@netlify/databaseand verify the database is reachable. When the command asks if you want to create sample data, decline — you’ll create your own baseline migration in the next step instead:Terminal window netlify database init -
Create an empty baseline migration with
netlify database migrations new:Terminal window netlify database migrations new -d baseline -
Populate the new migration’s
migration.sqlfile with the current shape of your source database. The fastest way is a schema-only export:Terminal window pg_dump --schema-only --no-owner --no-privileges "$SOURCE_DATABASE_URL"What matters is that running this migration against an empty database leaves it with the right shape. If you already have Drizzle migrations, skip the
migrations newstep, pointdrizzle-kitatnetlify/database/migrations/(see Tooling), and move your existing migrations in instead. -
Push the branch. Netlify detects
@netlify/database, provisions a preview database branch, and applies your baseline migration. The preview goes live still serving from the source database — your app code hasn’t changed yet. -
Confirm the baseline applied cleanly on the preview branch:
Terminal window netlify database status --branch <preview-branch> -
Merge the branch. Netlify provisions the production database branch and applies the baseline migration there too. Production still serves from the source.
If the baseline migration fails on the preview, the deploy preview fails and production is unaffected. Iterate on the migration until a clean preview deploy confirms your schema is reproducible from nothing.
Phase 2 — Swap the code and rehearse on a preview
Section titled “Phase 2 — Swap the code and rehearse on a preview”The goal of Phase 2 is to have the new production code working against Netlify Database, proven against a real preview deploy with real data.
On a new branch:
-
Update your application code to read and write through
@netlify/database. Wire Drizzle to the native Netlify Database adapter:db/index.ts import { drizzle } from "drizzle-orm/netlify-db";import * as schema from "./schema";export const db = drizzle({ schema }); -
Push the branch. Netlify creates a preview deploy with its own preview database branch, forked from the (empty) production Netlify Database.
-
Get the preview branch’s connection string with credentials:
Terminal window netlify database status --branch <preview-branch> --show-credentials -
Copy a snapshot of data from your source database into the preview branch. The schema is already in place from Phase 1, so dump and restore data only:
Terminal window pg_dump -Fc --data-only "$SOURCE_DATABASE_URL" | pg_restore --no-owner --no-acl --dbname="$PREVIEW_DATABASE_URL" -
Exercise the preview URL. Click through reads and writes. Validate the critical flows of your application end-to-end.
-
If something’s off, iterate on the branch and push again. Each push gets a fresh preview branch, so you can re-rehearse until the path is clean.
The rehearsal is the core of this flow. By the time the preview looks right, you’ve proven both the code swap and the data move against a real deployed environment. The production cutover is a re-run of a path you’ve already validated.
Phase 3 — Cut over production
Section titled “Phase 3 — Cut over production”When the rehearsal is clean, cut production over.
-
Get the production database connection string with credentials:
Terminal window netlify database status --show-credentials -
Export data from the source and import into the production Netlify Database:
Terminal window pg_dump -Fc --data-only "$SOURCE_DATABASE_URL" | pg_restore --no-owner --no-acl --dbname="$PRODUCTION_DATABASE_URL" -
Merge the Phase 2 branch to trigger a production deploy. Once it completes, your app reads and writes through Netlify Database.
-
Confirm reads and writes against the new production database.
Rolling back
Section titled “Rolling back”Each phase is independently reversible. Your source database keeps serving production traffic until the Phase 2 merge, so any rollback before that has no user-visible impact.
- Before merging Phase 2 — abandon the Phase 2 branch. Phase 1 left an empty Netlify Database behind a baseline migration; that’s harmless.
- After merging Phase 2 — revert the merge in the Netlify UI. The app redeploys with the previous code, which still reads from the source database. Keep the source running and its credentials live until you’ve had production on Netlify Database long enough to trust the switch.
Cleanup
Section titled “Cleanup”Once production has been stable on Netlify Database for long enough to trust the switch:
- Remove the source database client from your dependencies and any source connection strings from your Netlify environment variables.
- Decommission the source database in its hosting provider.
Next steps
Section titled “Next steps”- Migrations — deeper reference on the migration workflow
- Local development — develop against the embedded Postgres
- CLI reference — full list of
netlify databasecommands
Did you find this doc useful?
Your feedback helps us improve our docs.