Moving an existing project in without a password reset
Existing projects need an importer that preserves user IDs. Here is how scribase import moves a live project in.
"Switch in one line" is a great slogan and a useless migration plan. Wire compatibility means a new app can point at us. It does nothing for the existing project with 40 tables, 12,000 users, and 300 GB of files.
So we built the importer.
What scribase import moves
export SCRIBASE_SOURCE_CONNECTION_STRING='postgresql://postgres:…@db.abcd1234.example.com:5432/postgres'
export SCRIBASE_SOURCE_SERVICE_KEY='eyJ…'
scribase import supabase --project-ref abcd1234 \
--org acme --project store --env production --dry-run
The dry run connects with your project's connection string and service key, targets the Scribase organization, project, and environment you name, and prints exactly what will move and what will not — before you commit to anything. When you run it for real, it moves:
- Schema via
pg_dump --schema-only, linted and applied. - Data with chunked, resumable
COPYstreaming. auth.users, identities, and MFA factors — preserving user IDs so JWTs and foreign keys stay valid.- Storage buckets and object bytes with metadata.
- RLS policies, grants, and roles.
- Edge functions, best-effort, with a report of anything it could not take.
The line that matters
User IDs are preserved. That single decision is why existing sessions and password logins keep working after the move — no forced password reset. If a migration makes every user reset their password, it is not a migration, it is an outage with a nicer name.
The dry run is the sales tool
Because the dry run prints the full inventory of what moves and what needs a human, you can run it against a real project on a call and answer "will this work for us?" with a manifest instead of a maybe.
The acceptance test is blunt: a real hosted project imports and its existing users log in without resetting passwords. If that is not true, the importer is not done.