Short answer

Neon gives each Git feature branch its own Postgres branch. Each branch is a writable copy of the parent at a point in time, with a separate compute and connection string. Storage is copy-on-write, so a new branch adds no storage at creation and only bills for the pages you change.

Why per-branch databases

Sharing one staging database between feature branches creates conflicts. Two developers running migrations on the same schema can leave the database in a state neither expected. Provisioning a full staging instance per branch is too slow and too expensive on a traditional Postgres setup.

The Lakebase Postgres architecture separates storage from compute, so a branch is mostly metadata. Create one in a few seconds, run your migration against it, point your preview deployment at its connection string, and tear it down when the pull request merges.

Setting it up

A common pattern is GitHub Actions plus the Neon CLI:

# .github/workflows/preview.yml
- name: Create Neon branch for PR
  run: |
    neon branches create \
      --name preview/pr-${{ github.event.pull_request.number }} \
      --parent main \
      --expires-at "$(date -u -d '+7 days' +%Y-%m-%dT%H:%M:%SZ)"

For Vercel users, the Vercel-Managed Integration handles the same flow automatically. Every Preview Deployment gets a fresh branch with environment variables injected at build time. See the GitHub Actions guide for a full example.

Branch expiration

Stale branches add storage cost. Set a TTL when you create the branch:

  • 1 hour, 1 day, or 7 days from the Console
  • Any RFC 3339 timestamp via --expires-at on the CLI or expires_at on the API (up to 30 days ahead)

The branch is deleted automatically when it expires.

Plan limits

PlanBranches per projectExtra branches
Free plan10Not available
Launch plan10$1.50/branch-month (~$0.002/hour)
Scale plan25$1.50/branch-month (~$0.002/hour)

The hard maximum is 5,000 branches per project on paid plans. For teams running large preview-per-PR flows, that's enough to keep weeks of open PRs simultaneously.

How other Postgres options compare

  • Supabase. Supabase Branching creates a separate Postgres environment per Git pull request and runs your migrations on it, but no production data is copied to the preview branch. You seed it from a seed.sql file. Each branch runs as its own compute add-on, starting at about $0.01344/hour. Preview branches auto-pause on inactivity, and paused compute isn't billed, so you pay for running hours rather than the branch's whole lifetime.

  • Amazon Aurora. Aurora cloning is copy-on-write at the storage layer and includes parent data, but each clone is a full Aurora cluster billed at cluster rates. There's no Git-integrated workflow; you'd build one with Lambda or CDK.

  • Amazon RDS for Postgres. No native per-branch databases. Most teams use snapshot-and-restore, which copies the full dataset and provisions a fresh instance per environment.

Lakebase Postgres branches include the parent's data by default (or no data, if you prefer a schema-only branch). Compute on an idle branch scales to zero, so unused preview branches don't accrue CU-hours; you still pay for any storage delta on the branch.

Branch Postgres like you branch code

Free plan includes 10 branches per project with no credit card.