My goal is to optimize my app's architecture for cost when using Firebase Cloud Firestore. I understand Cloud Firestore's pricing model is on a per read/write basis. So I'm considering the following pattern for cost optimization purposes. I want to know whether it's "best practice" or an anti-pattern.
The idea is that whenever I create a new document to add to a collection, I will have the user update a second "master document" that contains some subset of the doc content plus the same from many similar docs from many different users.
Then, when I go to fetch the list data, instead of fetching a collection and getting charges for each document read from the collection (many reads), I retrieve only the master document instead (one read).
In code, it would look as follows.
Instead of this:db.collection("reviews")
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
I do this:
const docRef = db.collection("reviews").doc("MasterList");
docRef.get().then(doc => {
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
Is this a cost-wise best-practice? Or is this an anti-pattern?
Keep the rate of documents the database pushes to all clients under 1,000,000 documents/second. This is a soft limit. Cloud Firestore does not stop you from surpassing this threshold but it greatly affects performance. Keep the maximum document size downloaded by an individual client under 10 KiB/second.
Learn more about charges for operations in Cloud Firestore . Storage: You're charged for the data you store in Cloud Firestore, including metadata and indexes. Examples of metadata include document names, collection IDs, and field names. Index entries typically include the collection ID, the field values indexed, and the document name.
To model this data for Cloud Firestore, we can write the following document shapes: With this data model, we can easily store polymorphic data in the posts collection. To resolve the type of the post after reading from the database, we just need to look at the type field:
Firebase Authentication integrates directly with Cloud Firestore so you don't need to run your own authentication service. Push notifications: Send messages and notifications with Cloud Messaging.
Edit: Aug, 27th 2021
I wrote an article on this topic for a better understanding:
The idea of having a "master document" is a good one because you'll be able to make a single write operation even if you change multiple properties within it but there is a problem regarding a constraint, documents have limits. So there are some limits when it comes to how much data you can put into a document. According to the official documentation regarding usage and limits:
Maximum size for a document: 1 MiB (1,048,576 bytes)
As you can see, you are limited to 1 MiB total of data in a single document. When we are talking about storing text, you can store pretty much but as your document getts bigger, be careful about this limitation.
Cloud Firestore is optimized for storing large collections of small documents. So you should take advantage of this feature. Even if you need to duplicate and update several documents within separate collections, I recommend you go ahead in this way.
P.S. If you worry about costs, take also a look at Firebase realtime database and try to use them together. Are working pretty fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With