Docs

Tutorial: move a Supabase app to Sovaria

A step-by-step move of a real Supabase app: dry run, import, check the data and the rules, keep your users' passwords, switch the app's client code, and plan the cut-over.

Updated Oct 24, 2026

This walks through a whole move, from the first dry run to switching traffic. What the importer does and how each piece maps is in Migrate from Supabase or Firebase; this page is the order to do it in, and how to check each step.

#1. Prepare

  • Create the Sovaria project in the region nearest your Supabase project, so the copy is fast and latency stays the same.
  • Install the CLI and sign in as an owner or admin: npm install -g @sovaria/cli, sov login, sov scope pick.
  • Install pg_dump and psql 15 or newer. Copy the Supabase database connection string (Project settings › Database) and the service_role key (for storage).
  • Note what the importer doesn't move: Edge Functions (Deno code), cron jobs, database webhooks and auth email templates. You will recreate those in step 6.

#2. Dry run

export SUPABASE_DB='postgresql://postgres:PASSWORD@db.REF.supabase.co:5432/postgres'
sov import supabase --db-url "$SUPABASE_DB" \
  --supabase-url https://REF.supabase.co --service-key "$SUPABASE_SERVICE_ROLE_KEY" --dry-run

Nothing is written. Read the report: extensions to turn on first (Extensions), policies that will be rewritten (TO authenticated → auth.uid() IS NOT NULL), and anything it can't import.

#3. Import

sov import supabase --db-url "$SUPABASE_DB" \
  --supabase-url https://REF.supabase.co --service-key "$SUPABASE_SERVICE_ROLE_KEY"
# parts on their own: --only schema,auth   (then --only data,storage)

It runs schema, then users, then data, then storage, and writes sovaria-import-report.json. The schema arrives as one migration, so it shows in Version history: see, undo and restore changes and can be rolled back as a unit.

#4. Check that everything arrived

  1. Row counts

    Run the same count on both sides and compare.

    select relname as table, n_live_tup as rows
    from pg_stat_user_tables where schemaname = 'public' order by relname;
  2. Passwords

    Sign in as a test user with their old password through the SDK (await sovaria.auth.signIn(email, oldPassword)). Supabase's bcrypt hashes are used as they are, so nobody has to reset.

  3. Rules

    Run a simulation: every table as a visitor, a signed-in user and each role, compared with what your policies intend.

    sov sim run --fail-on critical
  4. Storage

    Compare object counts per bucket in Storage. Bucket privacy (public or private) is copied.

#5. Switch the app

Table and function calls through supabase-js keep working against Sovaria's REST endpoint (HTTP API). Auth moves to the Sovaria SDK, and supabase-js sends its session token through its accessToken option (supabase-js 2.45 or newer).

import { createClient } from '@supabase/supabase-js'

export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
await supabase.auth.signInWithPassword({ email, password })
const { data } = await supabase.from('notes').select('id, body').order('id', { ascending: false })
  • Moving queries to sovaria.data.sql or sovaria.data.rpc over time is optional. Both run under the same rules.
  • Storage calls move to sovaria.storage (Working with files). File paths are kept, so stored paths in your tables still point at the right files.
  • Add your site's origin under Project settings › API (Allowed origins (CORS) for browser apps) and register mobile apps and redirect URLs under Authentication.

#6. Recreate functions, schedules and webhooks

SupabaseSovaria
Edge Function (Deno)A function in Node.js, TypeScript on Bun, Python or Go. Deno.env.get becomes process.env, and Deno.serve becomes export async function handler(event, context) (Functions).
pg_cron jobA function schedule (Event triggers).
Database webhookA database webhook or a db.row trigger (Database webhooks).
Auth hooksAuth hooks, including blocking before-sign-up and before-sign-in hooks (Auth event hooks, Blocking hooks (before create, before sign-in)).
Email templatesAuthentication › Emails (Auth emails).

#7. Cut over

  • The importer copies a snapshot; it doesn't keep the two projects in sync. Plan a short write freeze: put the app in read-only mode, run the data import into a fresh project (or --only data,storage after clearing the rehearsal's tables), check counts, then release the new app version.
  • Rehearse the whole sequence once on a copy so you know how long the freeze takes.
  • Keep the Supabase project read-only for a week or two as a fallback before you delete it.

#Coming from Firebase or Supabase?

PlatformWhat this is called there
SupabaseSupabase migration
SovariaTutorial: move a Supabase app to Sovaria

Moving an existing app? Migrate from Supabase or Firebase imports users (with their passwords), data, files and rules.