Tutorial: move a Firebase app to Sovaria
A step-by-step move of a Firebase app: export Auth with its password hashes, import Firestore and Storage, turn security rules into policies, keep your Firestore code with an import change, and move Cloud Functions.
This walks through a whole move, from exporting users to switching traffic. The importer's details are 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, install the CLI and sign in:
npm install -g @sovaria/cli,sov login,sov scope pick. - Create a Firebase service account with read access to Firestore and Storage, and download its JSON (
sa.json). - Copy the password hash parameters: Firebase console › Authentication › Users › ⋮ › Password hash parameters, saved as
hash.json. - Copy your
firestore.rulesfile.
firebase auth:export users.json --format=json --project YOUR_PROJECT#2. Dry run, then import
sov import firebase --service-account sa.json \
--auth-export users.json --hash-config hash.json --rules firestore.rules --dry-run
sov import firebase --service-account sa.json \
--auth-export users.json --hash-config hash.json --rules firestore.rules- Auth goes first, so the importer can write
sovaria-import-uid-map.json(old Firebase uid → new Sovaria user id) and replace old uids inside your documents, ids and paths.users/{uid}is still each user's own document. Turn that off with--keep-uidsonly if your app stores uids somewhere the importer can't see. - Every collection and subcollection keeps its path. Document ids with characters Sovaria doesn't allow are cleaned and listed in the report.
- Passwords keep working: Firebase's scrypt hash is checked on each user's first sign-in, then upgraded. Nobody has to reset.
#3. Turn security rules into policies
sovaria-rules-report.md lists every rule with its Sovaria equivalent: public, signed-in users, owner only, or a custom policy. Nothing is applied automatically. Add the policies under Policies (or with sov policy upsert), then prove them with a simulation.
match /users/{uid}/orders/{orderId} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}#4. Check that everything arrived
- Compare document counts for your main collections:
getCountFromServeron both sides, or the Collections page. - Sign in as a test user with their old password through the SDK (
await sov.auth.signIn(email, oldPassword)). - Open a few documents you know well and check nested maps, arrays and timestamps. Times are stored as ISO-8601 strings (Firebase-style code (Firestore API)).
- Compare Storage file counts per folder.
#5. Switch the app
import { initializeApp } from 'firebase/app'
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth'
import { getFirestore, collection, query, where, onSnapshot } from 'firebase/firestore'
const app = initializeApp(firebaseConfig)
await signInWithEmailAndPassword(getAuth(app), email, password)
const db = getFirestore(app)- Firestore code keeps working with the import change (Firebase-style code (Firestore API)). Auth and Storage calls move to the Sovaria SDK.
- Flutter, iOS and Android apps use the native SDKs (Mobile apps). Their collection APIs follow Firestore's, but the calls change, so plan time for it.
- Offline persistence works the Firebase way on the web (Offline-first apps).
#6. Move Cloud Functions
| Firebase | Sovaria |
|---|---|
onDocumentCreated('orders/{id}', …) | A trigger on db.document, resource orders, event document.created (Event triggers). |
onCall / onRequest | A function called with sovaria.functions.call or over POST /functions/v1/<name> (Functions). |
onSchedule | A function schedule (Event triggers). |
beforeUserCreated / beforeUserSignedIn | Blocking auth hooks (Blocking hooks (before create, before sign-in)). |
onObjectFinalized | A trigger on storage.object, event object.created. |
| Firebase Admin SDK in functions | Your project API with a server key from the function's secrets (Deploying and running functions). |
#7. Cut over
- The import is a snapshot. Plan a short write freeze, re-import the data into a fresh project, check counts, then release the app version that points at Sovaria.
- Users signed in to the old app have to sign in once more. Their passwords still work.
- Keep the Firebase project read-only for a week or two before you delete it.
#Coming from Firebase or Supabase?
| Platform | What this is called there |
|---|---|
| Firebase | Firebase migration |
| Sovaria | Tutorial: move a Firebase app to Sovaria |
Moving an existing app? Migrate from Supabase or Firebase imports users (with their passwords), data, files and rules.