Unbase

Quickstart

Run a full Supabase migration end to end.

Install

The fastest path is the guided runner — it asks what to migrate and runs it for you, prompting only for the connection details it still needs:

unbase            # launches the guided migration UI

Ways to get it:

  • Standalone binary — download the unbase executable for your OS and run it. No Node, npm, or Bun required. (Built with bun build --compile.)
  • npx — npx unbase (needs Node). The guided UI additionally needs Bun; the individual commands below run on plain Node.

Prefer to drive it yourself? Use the commands directly:

1. Configure

Create a .env in your working directory:

# Source (Supabase) — read only
SUPABASE_DB_URL="postgresql://..."   # direct or pooler connection string
SUPABASE_SERVICE_KEY="..."           # service_role key (for storage)
# SUPABASE_URL="https://<ref>.supabase.co"  # optional — auto-derived from SUPABASE_DB_URL

# Target database
TARGET_DB_URL="postgresql://..."     # Neon / RDS / plain Postgres

# Target storage (Cloudflare R2 shown; see Configuration for S3/GCS/MinIO)
STORAGE_ACCESS_KEY_ID="..."
STORAGE_SECRET_ACCESS_KEY="..."
STORAGE_BUCKET="..."
STORAGE_ACCOUNT_ID="..."                # R2; use STORAGE_ENDPOINT / STORAGE_REGION for S3/GCS/MinIO
STORAGE_PUBLIC_URL="https://cdn.example.com"

Prefer the direct connection string for large dumps, though the pooler URL also works. Unbase only ever reads from the source.

2. Create the target schema

Unbase loads data into an existing schema. Create your target tables first with your own migrations (Drizzle, Prisma, or restored DDL).

3. Run the phases

npx unbase extract --mirror   # snapshot DB + auth + storage bytes -> ./.unbase/ir
npx unbase storage            # upload objects to R2/S3
npx unbase rewrite            # repoint storage URLs in the snapshot
npx unbase load               # load rows into the target (FK-safe) + verify
npx unbase auth               # load users/accounts into Better Auth

4. Verify

load verifies automatically, but you can re-run it anytime:

npx unbase verify

It reconciles the snapshot's per-table counts against your target and reports any gaps.

On this page