How to limit Firestore queries with strict rules
Save money on the list query in Firestore
Let’s talk numbers. At the time I’ve published this article, the current free tier for Firestore was 50,000 reads a day. That may seem like enough, but, your project will eventually evolve, and the documents will start to add up. After the free tier, it starts to go directly to your billing account. The cost once again may seem low ($0.06 for 100,000 in regions like Europe) but as history has shown, many companies report that they haven’t paid enough attention to these situations and found themselves with some astronomic bills. 💰💰💰
There are a couple of steps we can take to protect ourselves from these situations, and in this article, we will set a limit to the number of documents we pull at one time by a single client by paginating the collection query.
Setting the limits
If you already started with Firestore you probably heard by now about the Firestore Rules, which allow you to provide access control and data validation in a simple yet expressive format. And, it’s exactly what we are going to use to limit our list actions.
Firestore Rules have two main operations: write, which has three sub categories- create, update and delete, and the read operation, which can be divided into two granular operations- get and list. List is used to control that specific operation without impacting the other operations, and that’s what we’ll use. See the example bellow:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow write: if true;
allow get: if true;
allow list: if isListQueryValid();
} // List query permissions
function isListQueryValid() { return request.query.limit < 15 }
}
}
As we can see in this example, we are allowing write and get operations, but for the list operation, we’ve made a special function: isListQueryValid
which will only allow queries with the limit set below 15.
After the query limit is set, we publish and test, and then all that is needed is to add the limit to the client query:
firebase.firestore().collection('posts').limit(14).get()
And that’s it! From now on, all the queries must be made with limits set, and there’s no more 100,000 results per query, which is quite nice.
But what about the rest of the list?
Enter the pagination with startAfter
, a very handy and very easy to use query cursor. Let’s take the limit example above for the posts. With that query, we are requesting the first 14 documents of the posts collection. Now to get the next 14 documents, we just need to set in the next query the start after method with the last document as argument. We are simply saying, show me the next 14 documents after this document.
This was just a quick example on iteration for the startAfter cursor. For production we probably need to add recursivity and some if’s around so it doesn’t explode 🔥.
Remember
Every time a document is read on Firestore, it counts towards your billing (with blaze plan, after the free tier) so be safe and work your way to mitigate inconvenient situations as much as possible.
Firelayer — Launch your Firebase MVP 10x faster with our templates
Jump-start your Firebase Project with this open source project