Firebase: The good, the bad, the awesome.

Firebase: The good, the bad, the awesome.

Introduction

One of my dev colleagues said this is the best era to be a frontend developer and this is true. There are technologies out there that empower us to make great applications of any kind; a couple of clicks and we are ready to use them from our front end.

Today we are going to cover one of these technologies, Firebase.

What is firebase?

Firebase is a backend as a service platform backed by Google that provides a set of tools to help developers build, release and monitor web, Android, and IOS apps as well as engage with your users.

We are talking about Authentication, Database, Storage, Real-Time Database, hosting, and others.

My background with firebase

I have built some with applications with firebase but not at its full strength until February when I built zen a productivity app to help myself to focus on my tasks primarily and to participate in the Vercel & Hasnode hackathon. From the launch of Zen to the date of this post I've used like 80/90% of the tools of firebase and here are my pains, the things that have made me fall in love with firebase and the ones that have been a little bit more difficult to digest.

At the end of this post you will gain:

  • An overview of the most important tools provided by firebase.
  • Know scenarios where firebase shines the most.
  • Limitations you could find when building apps with firebase.
  • Resources that served me to improve my firebase skills.

The good parts.

Auth

I think almost every developer starts an application with the authentication flow. With firebase, this process is joyful and fast. we have 12 options for sign-in providers from email, google, FB, GitHub to anonymous sessions.

image.png

And to enable is just set the credentials and click to enable:

image.png

In the project, we have access to the methods of auth like this:

export const register = async (email, password) => {
    return firebase.auth().createUserWithEmailAndPassword(email, password).catch(reason => {
        throw new Error(reason.message);
    })
}

export const login = async (email, password) => {
    return firebase.auth().signInWithEmailAndPassword(email, password).catch((reason) => {
        throw new Error(reason.message);
    })
}

And the last step is listen when the state change to set/unset the authenticated user.

    firebase.auth().onAuthStateChanged((user) => {
        if (user) {
           ...
            firebaseState.user = user;
        }
    })

image.png

Database.

We have two database options Firestore and Realtime Database; both of which provide built-in real-time features. coming from a MySQL background where you had to implement that functionality with other tools this is mind-blowing and a killer feature by firebase and makes it a go-to option for applications like chats, and collaboration tools.

Both are No-SQL document-based databases. Firestore is the more powerful providing advanced queries and rules. You can create a collection that contains documents and every document can have subcollections

image.png

It allows setting rules, which are conditions to allow access for collections and documents in your database. Here, for example, we are telling to allow users to create tasks for them and allow delete and update if the user is the owner of the task.

match /tasks/{taskId} {
  allow create: if request.auth != null && request.resource.data.user_uid == request.auth.uid;
  allow delete, update: if request.auth != null && resource.data.user_uid == request.auth.uid; 
}

But you can set more advanced rules for example, with Zen I will need a sharing option in version 2.0 where users can let other users see their boards. We saved the collection in documents/shared/$(userUid)/accounts/${taskOwnerId}

The rules below would translate into "If I am authenticated and the task is mine or belongs to a user sharing board with me let me read the task".

match /tasks/{taskId} {
  allow read: if (request.auth != null && resource.data.user_uid == request.auth.uid) || (exists(/databases/$(database)/documents/shared/$(request.auth.uid)/accounts/$(resource.data.user_uid))); 
}

Functions

Not everything can run in the frontend, there is sensitive data that requires being managed from a server.

Cloud Functions are the firebase way to run stuff on the server without the pain of maintaining your own server (A.K.A serverless) they are flexible and complement very well with the other firebase tools. You can trigger a function on user sign-ups with Auth, after write, update, delete a document in Firestore, run scheduled functions in the background, the sky is the limit.

image.png

They even have callables that are functions you define in your backend and can invoke them from the front end just with the name. no need to install Axios and make a call to an endpoint.

exports.shareMatrix = functions.https.onCall(async (data, context) => {
   const user = context.auth;
   // do stuff with data
  return "OK"
})

Defining the cloud function in the backend

...
 const shareMatrix = functions.httpsCallable('shareMatrix');
  shareMatrix(formData).then(() => {
    clearForm()
    emit('saved', formData)
  })
...

Invoking the function in the frontend

Other tools.

Other tools worth mentioning are Hosting, Storage and analytics

  • Hosting: Allow to deploy multiple sites in a firebase project with SSL by default. you can set custom domains and restore deployments to previous versions

image.png

  • Storage: Allow saving files images, videos, audios etc in the cloud for your firebase projects.

  • Analitycs: Free analytics to track most used features, users retention.

The bad.

  • Database: Working with relationships in Firestore is a pain, if you are working with relational data you can do two things denormalize your data, in other words, is okay to repeat in order to deliver a document with all the information you need in a single query the recommended way or do multiple queries to obtain your data, which is not recommended for the way Firestore is priced they count reads, writes, and deletes the free limit is good enough but if you app success you can be charged more if you applied a bad structure in your data.

image.png

  • Vendor lock-in: Remember the part Backed by google? well, firebase has many tools and the most you use the harder is to migrate parts to other platforms you become dependant on Google if they decide to raise their prices tomorrow you don't have an easy path to save your data and restore in another service.

  • There's not fixed pricing. It is not totally bad because many services work like that today but the fact that you can't predict the cost of your next invoices from an accounting point of view is bad for planning.

When to use firebase

  • When you need fast development it could be a plus, because firebase takes care of the harder parts on Auth, Storage, Hosting, Server, Real-Time, etc.

  • You need real-time features and your app doesn't need many relations.

  • When you also need a mobile version of your app with android, React Native, for example, I can say from my experience is a smooth transition.

  • Prototype MVP with low-cost solutions.

When firebase might not be the best alternative

  • Working with complex database relations
  • You don't want to be dependant on one vendor

Wrapping up

Firebase can help us develop apps faster with a low cost even in their paid option - needed to use functions-. It's a good option for validating ideas, build small side projects, and if you are like me, having fun trying interesting technologies.

If you like these features and you can check other alternatives like:

I hope you find it useful, let me know about any questions you have here or on Twitter. thanks for reading and have a nice day.