You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
How to Manage Costs in FirebaseEpisode 125 written by Jeff Delaney
Health Check: This lesson was last reviewed on and tested with these packages:
- Angular v6.1
- RxJS v6.2
- AngularFire2 v5.0.0-rc.11
Find an issue? Let's fix it
Source code for How to Manage Costs in Firebase on Github
The cloud can be expensive, especially if you fail to optimize your app for the provider’s pricing model. What’s worse is that you won’t feel pricing spikes until your app gets popular, at which point your life will be in total chaos. When your app starts going viral, your costs will increase by the second, so it’s best to make these optimizations early in the game.
This lesson was inspired by a recent article How we spent 30k USD in Firebase in less than 72 hours by Nicholas Contreras. Give it a read, but basically they had one bad line of code that caused their Firestore reads to go into the multi-billion range with about 2 million daily active users.
Get notified before your costs grow out of control by setting up a budget alert in the GCP console. You don’t want to wait a full month if your app is accruing costs at $600/hr.
The first place to make optimizations is on the client. An optimized app should make only one request to Firebase per unique data source - don’t make redundant requests to the backend for the same data. It’s common to see multiple components request the same document or collection, each firing off their own read operation to Firestore. When you scale up to millions of requests, these extra reads will double your baseline costs N times, where N is the number of redundant reads that exist in your code.
The code below creates three different Observables, even though they all rely on the same
RxJS and Angular makes it easy to share data among multiple subscribers. By just piping in the shareReplay operator we can multicast and cache the last emitted value with as many subscribers as we need.
Need to share data among multiple components? Create this Observable in a service and inject it as singleton.
Outside of RxJS, there are other ways to achieve similar behavior. But the general idea is to make requests to Firebase once, then share this single source across all views that need it.
The most powerful cost optimizations you can make are on the server by duplicating and aggregating data to fit the UI live a glove. A common strategy is to aggregate statistics about a collection after a new document is added to it. You can also duplicate a handful of documents into an embedded array to have a single document that contains the last 10 documents, thus reducing ten reads per user to just one.
You might be surprised at how easy this is to implement with a Cloud Function. Let’s imagine we have a collection of donations, but our UI needs to show the total amount and average donation across this collection. The function below will run after each new donation is created, then update a separate document with the new totals. The aggregation doc is what we read in the UI.
const functions = require('firebase-functions');
We now only need one document read per visitor, as opposed thousands per visitor when totaling up the collection clientside. Not only is this faster, but it could save tens of thousands of dollars in read costs.
Had the startup company used aggregation from the start, their Firebase costs would have been reduced from $30K to just $25 - a savings of 99.9%.