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 UIWays to get it:
- Standalone binary — download the
unbaseexecutable for your OS and run it. No Node, npm, or Bun required. (Built withbun 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 Auth4. Verify
load verifies automatically, but you can re-run it anytime:
npx unbase verifyIt reconciles the snapshot's per-table counts against your target and reports any gaps.