Short answer
Neon's branching model maps directly onto Git workflows. Every pull request gets its own database branch with its own connection string, created from production data in seconds and deleted when the PR closes. Migrations run on the branch first, then roll forward to main after review.
What the workflow looks like
A typical GitOps loop with Neon:
- Developer opens a feature branch in Git.
- CI calls the Neon API or CLI to create a child branch from
main. - Migrations run against the new branch as part of the build.
- Preview deployment gets the branch's connection string injected as an environment variable.
- PR merges, migration is applied to
main, child branch auto-expires.
In a GitHub Actions step:
- name: Create Neon branch
id: create-branch
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch_name: preview/pr-${{ github.event.pull_request.number }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run migrations
run: drizzle-kit migrate
env:
DATABASE_URL: ${{ steps.create-branch.outputs.db_url_pooled }}See the GitHub Actions guide for the full setup, including a cleanup workflow that deletes the branch when the PR closes.
Why this works on Neon's architecture
Branches are cheap because storage is versioned. A new branch records a pointer to the parent's state and only stores the pages it changes. Creating a branch of a 500 GB database doesn't copy 500 GB of data. The compute on each branch can scale to zero, so an idle preview branch costs storage delta only, not compute hours.
Built-in integrations
If you're on Vercel, the Vercel-Managed Integration wires the same flow up without a custom GitHub Action. Every Preview Deployment gets a fresh branch automatically.
For other providers, the Neon API is the integration point. Create, list, and delete branches from any CI provider that can run a shell command.
How other Postgres providers fit GitOps
-
Supabase. Supabase Branching ties preview branches directly to GitHub pull requests through the Supabase GitHub integration. Migrations in your
supabase/migrations/directory run automatically when the branch is created. Preview branches don't receive production data; they're seeded fromseed.sql. Each branch is a separate compute add-on billed from about $0.01344/hour for its lifetime. -
Amazon Aurora / RDS for PostgreSQL. No built-in PR integration. You typically script the workflow with Terraform, AWS CDK, or Lambda functions that create snapshots, restore them to fresh instances or Aurora clones, and wire connection strings into preview deployments. Aurora clones share storage; RDS snapshot-restore copies the dataset.
Neon's GitHub Action, Vercel-Managed Integration, and the @neondatabase/serverless driver are the parts of the system that make per-PR Postgres simple to wire in. Branches include parent data by default, and compute scales to zero when the preview deploy goes idle.

Free plan supports 10 branches per project for preview-per-PR.








