Over the years, I’ve developed something of a love/hate relationship with Firebase.
Sure, Firebase makes crafting new products and ideas a whole lot simpler. But it quickly becomes a burden…
At Slite, we decided to consider Firebase for what it is: an asset. Firebase gave us the ability to build a kick-ass product in under 10 months and to have it tested and used by 500 people — which would have been unthinkable 3 years ago.
And yet, planning for the transition from Day-1 is key to making the most out of Firebase. Knowing the limitations and preparing for the migration is pretty straightforward: you just have to stay rigorous, and do each step one at a time.
Firebase offers a full set of services, which aren’t free, but will save you a LOT of time:
- Realtime updates
- Offline resync upon reconnection
- File storage
- Third-party authentication providers
I assure you that, when you don’t have all of that to deal with, you’ll have a much clearer mind to focus on the tech bits that really matter. To us, that was building a rich collaborative editor. 🛠
How to initiate the move away from Firebase?
The first thing to do is to replace the services you won’t be able to migrate later. Hosting or authentication are so tied up with Firebase that you need to migrate them right away. Just keep the realtime updates and database in Firebase, the rest should belong to you.
- Hosting: We set up everything on Docker and hosted the service on App Engine.
- API: We started a small Node.js service to kickoff our API.
- Authentication: Thanks to our new API, we were able to generate JWT tokens for each user: one for our API and another for Firebase’s legacies.
- Database: We set up a Postgres to store users/organizations and invites which were in the first migration batch.
And then you have to get your hands dirty: with your API in place, you can run a migration from Firebase back to your database, to ensure that all your data remains synchronized. Basically, we used Firebase as a “slave” to our new database. 🤠
Choose to own your data
We use Firebase REST API ( especially the shallow query only available with REST) to list objects and migrate them one at a time. Once the migration is performed, users will consume our fresh API and mutate objects in our database. We then keep them up to date by syncing back to Firebase.
Example migration snippet:
Keep growing / keep migrating
At Slite, we’re bringing the future of knowledge to teams. Our core feature is a real-time collaborative editor. Its synchronization and storage were still on Firebase. It was inspired by Firepad in its design, but when we reached 50 users, we were stuck: 1GB database, without any possibility to restore a backup. In order to sync rich-text documents with operational transformation, you have to store each operation that occurred on the document.
As we had already started our hosting migration, we set up a new collaboration system based on ShareDB. Thanks to our Kubernetes and micro-services environment, we had the ability to host it pretty quickly.
Alongside, we migrated our search from a client-based custom solution to Algolia, with a hook on Firebase to sync on all object changes.
Use the right service for the right job
At this point, where are we?
✅ Hosting is provided by Google Cloud Platform with Kubernetes.
✅ Querying and mutating data is partially done via our Node.js API.
✅ Our collaboration system is hosted as a micro-service in Kubernetes.
✅ We own authentication by generating JWT for our API and Firebase.
✅ We tested our ability to migrate objects from Firebase to our database.
❌ Most of our business data still remains in Firebase.
❌ We are yet to set up a real-time system to publish updates to users.
Finishing the clean up
Now it’s time to finish the migration. We are currently developing our API with GraphQL and Node.js and are taking advantage of the fresh subscriptions system released recently (Kudos to the Apollo and GraphQL teams).
Bootstrapping our fresh new API with GraphQL brought us great velocity and documentation.
From day one, we separated concerns by having the least amount of Express controllers possible and separated functions to query or mutate data (by doing permissions verifications, database queries…). Setting a new way to expose endpoints with GraphQL was easy and we can still support our REST API. The flexibility provided gave us confidence as we moved towards our future challenges (mobile and external integrations).
Here is some advice if you have to tackle such a transition:
🚦Define a roadmap with clear steps to ensure the migration suite.
👋 Ask for help and read a lot to be confident in your choices.
🛠 Don’t hesitate to build a POC (proof of concept) if you are not sure about a choice.
📊 Keep a spreadsheet with the migration status of all the mutations, queries and objects.
✨ Enjoy every step, it’s hard and painful but it can be vital for your business.
This story was made possible by the entire Slite team (Arnaud Rinquin, Christophe Pasquier and Brieuc Sebillotte). If you fancy testing Slite, be sure to register at https://slite.com. And if you want to join the team building the future of collaboration, drop us a line at chris(at)slite(dot)com.
Thanks folks ✨ 👋 don’t forget to recommend the article if you liked it!