Supabase branching vs. separate staging projects
Published Jul 5, 2026 · 9 min read
Use Supabase branching for short-lived preview environments — PR reviews, migration testing in CI, quick experiments — and use a separate Supabase project for a long-lived staging environment. Branching requires a paid plan and bills $0.01344 per branch per hour, which makes an always-on branch cost about as much as a dedicated project, without the isolation benefits. A separate project gives you a persistent, independently billed environment; the trade-off is that you have to get your production structure into it yourself.
Both options are legitimate. This post walks through what branching actually does in 2026 (it changed with Branching 2.0), what it costs, where it clearly wins, and where a separate staging project is the better call.
What is Supabase branching and how does it work?
Supabase branching creates isolated copies of your project — each branch gets its own database instance, API endpoints, Auth settings, Storage buckets, and Edge Functions. Changes in one branch don't affect any other branch or production.
There are two kinds of branches:
- Preview branches are ephemeral. In the Git workflow, opening a pull request spins one up automatically; it runs the migrations in
./supabase/migrations, applies new migrations on each push, and is paused after inactivity or deleted when the PR is merged or closed. - Persistent branches are long-lived. Supabase recommends them for staging, QA, or development environments. They are not auto-paused or auto-deleted.
Since Branching 2.0, Git is no longer required: you can create branches directly from the dashboard, the CLI, or the Management API — with Git, without Git, or both.
Two properties matter for the staging question:
- Branches are data-less. From the Supabase docs: "New branches do not start with any data from your main project." You can seed a branch with
./supabase/seed.sql, but the seed runs exactly once, at branch creation. To reseed you delete and recreate the branch. - Git-based branches are built from your migration files, not from the live production schema. If your production schema has drifted — someone created a table or edited a policy in the dashboard without writing a migration — the branch won't reflect it. The gitless flow reduces this gap by dumping the current schema, but the migration-history model is still the source of truth for the CI workflow, and unmerged branches drift as soon as other work lands in production.
How much does Supabase branching cost?
Branching is available on the Pro plan and above — the Free plan doesn't include it. Per the Supabase pricing page and the branching usage docs:
- Each branch bills $0.01344 per hour on the default Micro compute size.
- Billing is purely usage-based: there is no fixed fee, and you pay for the hours a branch runs.
- Compute Credits do not apply to Branching Compute. The $10/month credit that offsets your main project's compute does not offset branches.
- Branch disk usage counts toward your plan's included 8 GB; beyond that, disk is billed like any other database.
The math that decides the staging question: a short-lived preview branch that runs 30 hours during a PR costs about $0.40. A persistent branch running 24/7 costs $0.01344 × 720 ≈ $9.70 per month — roughly the same as the Micro compute for an additional dedicated project, except credits can't reduce it. Branching is priced for ephemeral use. The moment a branch becomes permanent, its cost advantage disappears.
What is Supabase branching great at?
Being fair here matters, because branching genuinely wins several workflows:
- PR preview environments. Open a PR, get a full isolated Supabase stack with its own credentials, wired into Vercel or your CI. Nothing else gives you this with so little setup.
- Migration testing in CI. Every push replays new migrations against the branch. If a migration fails, you find out in the PR — not during a production deploy. If you manage migrations in Git, this alone justifies branching.
- Cheap, disposable experiments. Cents per day, one click to create since Branching 2.0, zero cleanup guilt. Testing a risky schema refactor against a throwaway environment is exactly what per-hour billing is for.
- Merge-to-promote workflows. Merging a branch can promote its migrations to production, keeping your database changes on the same rails as your code changes.
If your team is on the Pro plan, keeps its schema in migration files, and wants per-PR environments, use branching. A separate project is the wrong tool for that job — provisioning and tearing down projects per PR is slow and manual.
What are the limits of Supabase branching?
The constraints that push teams toward a separate project:
- Paid plan required. No branching on the Free plan. If you're a solo dev or a small team on free-tier projects, branching isn't even on the menu.
- Per-hour billing punishes persistence. A staging environment is by definition always-on. At ~$9.70/month per persistent branch — uncovered by Compute Credits — you're paying dedicated-project money for something that still lives inside your production project's org and lifecycle.
- No production data, by design. Branches start empty to protect sensitive data. That's the right default, but it means "staging that mirrors prod data" isn't what branching gives you — you're maintaining seed files either way, and the seed only runs at branch creation.
- Migrations are the source of truth. Anything not captured in
./supabase/migrations— dashboard-created tables, hand-edited RLS policies, that index someone added during an incident — won't exist on a Git-based branch. Teams with schema drift get branches that don't match production and often don't notice until something behaves differently. - Same org, same blast radius. A branch is a child of your production project. If you want staging in a different organization (separate billing, separate access control, contractors who should never see prod), branching can't do that.
When is a separate staging project the better fit?
A dedicated Supabase project wins when the environment is long-lived and organizationally distinct:
- Persistent staging/QA. An environment that's always there, with stable URLs and keys your team and CI pipelines reference for months. See our guide to setting up a Supabase staging environment for the full setup.
- Cost control. A staging project can live in a Free-plan org at $0 (with the caveat that free projects pause after a week of inactivity — fine for many staging setups, or $10/month on Pro keeps it always-on). A persistent branch can never be free.
- Free-tier teams. If production itself is on the Free plan, a second free project is your only option — and it's a perfectly good one.
- Org and access separation. Different organization, different members, different billing entity. Staging credentials that can't touch prod even in principle.
- True independence. A separate project has no lifecycle coupling to production: no auto-pause rules tied to PRs, no migration-history dependency, no risk that a branching workflow change affects it.
Most teams running a dev → staging → prod workflow land on a hybrid: preview branches for PRs, plus one separate long-lived staging project.
Supabase branching vs. separate project: comparison
| Preview branches | Separate staging project | |
|---|---|---|
| Best for | PR previews, CI migration tests, experiments | Long-lived staging/QA environments |
| Plan requirement | Pro plan or above | Any plan, incl. Free |
| Billing | $0.01344/branch/hour (credits don't apply) | Free tier, or normal project compute |
| Cost if always-on | ~$9.70/month per branch | $0 (Free, pauses when idle) – $10/month (Pro Micro) |
| Starting state | Migrations replayed / schema dump; no data | Empty — you bring the structure |
| Schema drift risk | Yes — dashboard changes outside migrations are missing | No — you clone the live schema state |
| Lifecycle | Auto-pause/delete (preview) or manual (persistent) | Fully independent |
| Org/billing separation | No — lives inside the production project | Yes — any org, any plan |
| Setup effort | One click / automatic per PR | Manual — schema, policies, functions must be recreated |
How do you get production structure into a separate staging project?
The honest weakness of the separate-project approach is the last row of that table: a fresh project is empty, and recreating your schema, RLS policies, functions, triggers, and indexes by hand — or wrestling pg_dump past Supabase-managed schemas — is where most teams stall. The classic failure mode is dumping everything including auth and storage schemas and hitting permission denied errors on restore; our pg_dump and pg_restore guide covers those pitfalls in detail.
SupaClone automates exactly this step. It clones your production project's structure — schemas, tables, RLS policies, functions, triggers, indexes, views, enums, extensions — into a fresh, empty target project using native pg_dump/pg_restore with a baseline-aware plan that correctly skips the Supabase-managed schemas (auth, storage, realtime). Because it reads the live database, dashboard-made changes that never became migration files come along too — the drift problem that bites Git-based branches doesn't apply. Optional add-ons cover Storage buckets and Edge Functions; secrets are never copied and are listed as manual steps in the report instead. Every run ends with field-by-field verification and a full report of what was cloned, skipped, failed, or needs a manual step. Connection is via Supabase OAuth — no connection strings to handle. Pro is $7/month with a 14-day free trial including one successful clone.
Note the scope honestly: SupaClone clones structure today, not table data — data clones (exact and anonymized) are coming soon. For seeding staging with data you'll still script inserts or use pg_dump --data-only selectively.
Which should you use?
- Per-PR environments and CI migration testing: branching, no contest.
- Always-on staging on a budget or on the Free plan: separate project.
- Staging that must match live production structure (including drift): separate project, cloned from prod — the full walkthrough is here.
- Org/billing/access separation: separate project.
- Both needs: run both. Preview branches for PRs, one separate staging project for release testing.
FAQ
Is Supabase branching free?
No. Branching requires the Pro plan or above and bills $0.01344 per branch per hour on the default Micro compute size. Compute Credits do not apply to branching compute, so branches always add to your bill.
Do Supabase branches copy production data?
No. New branches start with no data from your main project — this is deliberate, to protect sensitive production data. You can seed a branch with supabase/seed.sql, but the seed runs only once, when the branch is created.
Can I use a persistent branch as my staging environment?
You can — Supabase recommends persistent branches for staging and QA. But an always-on branch costs roughly $9.70/month uncovered by credits, lives inside your production project's org, and (on the Git workflow) only contains what your migration files describe. A separate project is often cheaper and more isolated for this role.
Does branching still require GitHub?
Not anymore. Since Branching 2.0 you can create and manage branches from the dashboard, the Supabase CLI, or the Management API — with or without Git. The automatic PR-preview workflow still uses the GitHub integration.
How do I make my separate staging project match production?
Either replay your migration history (if it's complete and drift-free) or clone the live structure. SupaClone copies schemas, tables, RLS policies, functions, triggers, indexes, views, enums, and extensions from your production project into a fresh empty project and verifies every field afterward — including changes that were only ever made in the dashboard.