How to optimize firestore read per app launch - firebase

Understand firestore charge based on read / write operation.
But I notice that the firestore read from server per app launch, it will cause a big read count if many user open the app quite frequent.
Q1 Can I just limit user read from server for first time login. After that it just read for those update document per app launch?
For example there's a chat app group.
100 users
100 message
100 app launch / user / day
It will become 1,000,000 read count per day?
Which is ridiculous high.
Q2 Read is count per document, doesn't matter is root collection / sub collection, right?
For example, I read from a root collection that contain 10 subcollection and each of them having 10 documents, which will result 100 read count, am i right?
Thanks.

That’s correct, Cloud Firestore cares less about the amount of downloaded data and more about the number of performed operations.
As Cloud Firestore’s pricing depends on the number of reads, writes, and deletes that you perform, it means that if you had 100 users communicating within one chat room, each of the users would get an update once someone sends a message in that chat, therefore, increasing the number of read operations.
Since the number of read operations would be very much affected by the number of people in the same chatroom, Cloud Firestore suits best (price-wise) for a person-to-person chat app.
However, you could structure your app to have more chat rooms in order to decrease the volume of reads. Here you can see how to store different chat rooms, while the following link will guide you to the best practices on how to optimize your Cloud Firestore realtime updates.
Please keep in mind that Cloud Firestore itself does not have any rate limiting by default. However, Google Cloud Platform, has configurable billing alerts that apply to your entire project.
You can also limit the billing to $25/month by using the Flame plan, and if there is anything unclear in your bill, you can always contact Firebase support for help.
Regarding your second question, a read occurs any time a client gets data from a document. Remember, only the documents that are retrieved are counted - Cloud Firestore does searching through indexes, not the documents themselves.
By using subcollections, you can still retrieve data from a single document, which will count only as 1 read, or you can use a collection group query that will retrieve all the documents within the subcollection, counting into multiple reads depending on the amount of documents (in the example you put, it would be 10x10 = 100).

Related

Is there a way to limit the size of a collection in firebase firestore?

I am using a collection in Firebase Firestore to log some activities but I don't want this log collection to grow forever. Is there a way to set a limit to the number of documents in a collection or a size limit for the whole collection or get a notification if it passes a limit?
OR is there a way to automatically delete old documents in a collection just by settings and not writing some cron job or scheduled function?
Alternatively, what options are there to create a rotational logging system for client activities in Firebase?
I don't want this log collection to grow forever.
Why not? There are no downsides. In Firestore the performance depends on the number of documents you request and not on the number of documents you search. So it doesn't really matter if you search 10 documents in a collection of 100 documents or in a collection of 100 MIL documents, the response time will always be the same. As you can see, the number of documents within a collection is irrelevant.
Is there a way to set a limit to the number of documents in a collection or a size limit for the whole collection or get a notification if it passes a limit?
There is no built-in mechanism for that. However, you can create one mechanism yourself in a very simple way. Meaning, that you can create a document in which you can increment/decrement a numeric value, each time a document is added or deleted from the collection. Once you hit the limit, you can restrict the addition of documents in that particular collection.
OR is there a way to automatically delete old documents in a collection just by settings and not writing some cron job or scheduled function?
There is also no automatic operation that can help you achieve that. You can either use the solution above and once you hit the limit + 1, you can delete the oldest document. Or you can use a Cloud Function for Firebase to achieve the same thing. I cannot see any reason why you should use a cron job. You can use a Cloud Scheduler to perform some operation at a specific time, but as I understand you want it to happen automatically when you hit the limit.
Alternatively, what options are there to create a rotational logging system for client activities in Firebase?
If you still don't want to have larger collections, maybe you can export the data into a file and add that file to Cloud Storage for Firebase.

Number of READS in firestore and the basis of its calculation

I still fail to understand the calculation of no. of reads on Firestore. Just as an experiment, I just sat a the Firestore console without doing anything, no devices connected, no mobile, no emulator nothing, and the no. of reads registered in under the usage TAB was about 600 reads in about 10 minutes. So my guess is, if it's a real app out there, 50000 reads will be breached in no time at all! Can someone please explain FIRESTORE READS and its fundamentals?
The number of reads in Firestore is always equal to the number of documents that are returned from the server by a query. Let's say you have a collection of 1 million documents, but your query only returns 10 documents, then you'll have to pay only 10 document reads.
If your query yields no results, according to the official documentation regarding Firestore pricing, it said that:
Minimum charge for queries
There is a minimum charge of one document read for each query that you perform, even if the query returns no results.
Those unexpected reads most likely come from the fact that you are using the Firebase console. All operations that you perform in the console are counted towards the total quota. So please remember to not keeping your Firebase console open, as it is considered another Firestore client that reads data. So you'll be also billed for the reads that are coming from the console.

Cloud Firestore Payments

I have a question regarding payment at the Cloud Firestore compared to the Realtime Database. At Firestore you pay per read/write per document, right? In other words: If I display a list of 1000 documents in a collection, do I pay for 1000 reads?
I have a few collections in my app with many (200-300) documents, which unfortunately all have to be displayed on one page. My app has about 10,000 active users. After the calculation I am definitely financially broke... :-)
Therefore my question: Are 300 elements also 300 reads taken into account if I save the 300 elements in ONE document as an Array and retrieve them? Is then only the one document calculated as a read? Or also the 300 elements from the created array?
If I display a list of 1000 documents in a collection, do I pay for 1000 reads?
You only pay for documents that are read on/from the server. Most Firestore SDKs implement a client-side cache, which may significantly reduce the number of documents that are read on/from the server.
I have a few collections in my app with many (200-300) documents, which unfortunately all have to be displayed on one page
One way to reduce the number of read operations is to model the data for that one page into a separate single document. This document is essentially the data for a single page in your app, meaning that you update it whenever any of the underlying data updates. That leads to more code when you write updates to the database, but it saves you 299 document reads for every user accessing the page.
Also see:
Cloud Firestore Pricing | Get to Know Cloud Firestore #3
Firestore: How are "reads" calculated for the quota?
Firebase firestore pricing for querying
Understanding Firestore Pricing

Firestore query costs

On Firestore I have a social app that stores each user as a document, and queries based on users within a certain distance.
If a user launched the app and had 1,000 users within 50 miles for example, would I be charged for 1000 reads for downloading all nearby profiles? That seems like it would be hyper expensive if I got charged that much every time a user queried nearby users. Is there a cheaper way to do this?
As far as I know, if your query returns 1 document, you'll be charged 1 read. If your query returns 1000 documents, you'll be charged 1000 reads.
I'm not sure how your app might look like, I'd rather re-structure fetching process. For instance, I'd rather not fetch the entire 1000 users at once.
Instead, the way of getting a fresh set of 10 or 20 group of nearby users whenever a person wants to see new users seems much better to me.
Hope this helps you.
Note: Be aware that your queries won't get any extra charges for having supplementary documents in a collection that are unread.
Have a look at Managing large result sets which help you manage queries that return a large number of results.
You can use Realtime Database as an alternative. It seems cheaper than Firestore. No document read. 10 GB is free and it means 200 million chat messages.
I use Blaze plan and i only pay for Firestore Reads. I plan to migrate some tables to old Realtime Database. I have 10.000+ users. I just show a calendar & dining menu to them from Firestore. I don't want to pay for such simple things.

Understanding Firestore Pricing

Before creating a new app I wanna make sure I get the pricing model correct.
For example in a phonebook app, I have a collection called userList that has a list of users which are individual documents.
I have 50k users on my list, which means I have 50k documents in my collection.
If I were to get the userList collection it will read all 50k documents.
FireStore allows 50k document reads. Does that mean 50k document reads in total or 50k document read per document?
As in the example of my phonebook app if it is 50k document reads in total I will run out of the free limit in just one get call.
If you actually have to pull an entire collection of 50k documents, the question you likely should be asking is how to properly structure a Firestore Database.
More than likely you need to filter these documents based on some criteria within them by using the query WHERE clause. Having each client device hold 50k documents locally sounds like poor database planning and possibly a security risk.
Each returned document from your query counts as 1 read. If there are no matches to your query, 1 read is charged. If there are 50k matches, there are 50k reads charged.
For example, you can retrieve the logged in user's document and be charged 1 read with something like:
db.collection('userList').where('uid', '==', clientUID)
Note: As of 10/2018 Firestore charges 6 cents (USD) per 100k reads after the first 50k/ day.
The free quota is for your entire project. So you're allowed 50.000 document reads under the entire project.
Reading 50K user profile documents will indeed use that free quota in one go.
Reading large numbers of documents is in general something you should try to prevent when using NoSQL databases.
The client apps that access Firestore should only read data that they're going to immediately show to the user. And there's no way you'll fit 50K users on a screen.
So more likely you have a case where you're aggregating over the user collection. E.g. things like:
Count the number of users
Count the number of users named Frank
Calculate the average length of the user names
NoSQL databases are usually more limited in their query capabilities than traditional relational databases, because they focus on ensuring read-scalability. You'll frequently do extra work when something is written to the database, if in exchange you can get better performance when reading from the database.
For better performance you'll want to store these aggregation values in the database, and then update them whenever a user profile is written. So you'll have a "userCount", a document with "userCount for each unique username", and a "averageUsernameLength".
For an example of how to run such aggregation queries, see: https://firebase.google.com/docs/firestore/solutions/aggregation. For lower write volumes, you can also consider using Cloud Functions to update the counters.
Don't call all users in one go. You can limit your query to get a limited number of users. And when a user will scroll your query will get more users. And as no one is going to scroll fro 50k users so you can get rid of a bundle of cost. This is something like saving memory in case of recycle view.

Resources