Short answer
Neon lets you test a migration on a writable copy of production data, then roll the parent branch back to any point in the history window if the same change breaks something later. Branches are copy-on-write, so testing against a 100 GB database doesn't require 100 GB of new storage.
The two safety mechanisms
Test on a branch first. Create a branch from main, run the migration there, and exercise it from a staging deployment. Other Postgres workloads keep running on main unaffected, because each branch has its own compute.
neon branches create --name test/add-user-flags --parent main
# Run the migration against the new branch's connection string
psql "$NEON_TEST_BRANCH_URL" -f migrations/2026-04-25-add-flags.sqlRestore if a deployed migration breaks production. Neon keeps a continuous change history as Postgres WAL. Use instant restore to return a branch to a timestamp before the bad change ran:
neon branches restore main ^self@2026-04-25T14:32:00ZThe history window is 6 hours on Free, up to 7 days on Launch, and up to 30 days on Scale.
A safer migration pattern
A common pattern combining both:
- Create
test/branch frommain. Run the migration. Verify your app works against it. - Promote the same migration to
mainin a controlled deploy. - If something downstream breaks within the history window, branch from
mainat the pre-migration timestamp, or restoremainin place.
Restore in place drops writes
Restoring main in place overwrites the branch's current state. Writes made after the target timestamp are gone. If you might need them for forensics, branch to a new name from the timestamp instead of restoring in place.
What about protected branches
On Launch and Scale, mark main as a protected branch to block accidental drops, restrict who can run destructive operations, and require IP allowlisting (Scale only). Treat it like a protected Git branch in your CI/CD.
How other Postgres options compare
-
Amazon Aurora. Aurora cloning gives you a writable copy-on-write copy of production data to test against. Rollback after a bad change uses PITR, which restores to a new cluster; you then swap connection strings.
-
Amazon RDS for PostgreSQL. No copy-on-write clone. Testing migrations against real data usually means snapshot-and-restore, which copies the full dataset to a new instance. PITR up to 35 days is the rollback path, and again restores to a new instance.
-
Supabase. Preview branches let you run migrations on a separate Postgres environment, but the preview is not seeded with production data. Rollback after a bad change uses daily logical backups or the PITR add-on (paid).
With Neon, the branch has parent data already, and a restore happens in place against the existing branch, so connection strings don't change.

Create a Neon branch, run your migration, throw the branch away.








