There are only a few real ways to count documents in Firestore.#
- Increment a counter
count
variable - Increment individual shard
count
variables and add them up - Use server aggregation functions like
SUM
andCOUNT
- Count the snapshot size
What else?#
That's it!
All methods below are just derivatives of the above. Sometimes you use the server to automatically count the latest version, and sometimes you just grab the latest increment on the client. You may need to sort your results, or you may need realtime updates. You may have a lot of traffic and you're worried about writing to these documents more than once a second. There are many challenges in Firestore that other databases may not have, but I tried to come up with a solution for each challenge.
TL;DR#
Method | ✅ Best For | ⚠️ Avoid When |
---|---|---|
Snapshot Size | Counting documents you have already queried. | Counting documents you have not already read. |
Server Count | Counting less than 1000 documents quickly, | Counting medium to large collections. Counting Queries with small results. |
Distributed Counter Extension | Counting views, counting high velocity likes, don’t need to keep track of each like | You don’t have more than one like per second, small sites, you need to keep track of information for each view or like |
Distributed Counters + Server Sum | You want to define the number of shards beforehand (maybe up to 20 or so), you don’t want to spin up a schedule function every second | You don’t need to write more than once per second, you don’t want to read all items for an aggregation on client |
Create Document + Server Count | You can just count the number of documents for a like, unique view, or action, and you need to store more information per action (IP address, user id, creation date, etc) | You don’t want to have your database overflown with lots of data you don’t need. An external API makes more sense (Google Analytics etc) |
Server Side Increment | Large Collection counts. Sorting by counters. You want to avoid complex rules. Saving price on counting. | You need to display a count once on small collections. You prefer dealing with Firestore rules over Firebase Functions. You worry about accuracy. |
Server Side Server Count | Large Collection counts. Sorting by counters. You want to avoid complex rules. You need accuracy. | You need to display a count once on small collections. You prefer dealing with Firestore rules over Firebase Functions. You don’t want to be charged for counting. |
Increment Transaction | Large Collection counts. Sorting by counters. Need for realtime counter. You want to avoid complex rules. Saving price on counting. | You need to display a count once on small collections. You prefer dealing with Firestore rules over Firebase Functions. You worry about accuracy. |
Server Count Transaction | Large Collection counts. Sorting by counters. Need for realtime counter. You want to avoid complex rules. You need accuracy. | You need to display a count once on small collections. You prefer dealing with Firestore rules over Firebase Functions. You don’t want to be charged for counting. |
Batch Increment | Large collection counts. Sorting by counters. Need for realtime counter. | You need to display a count once on small collections. You prefer firebase functions over Firestore rules. |
Choosing the Right Counter#
Generally speaking, distributed counters will solve the write problem of one second or more. Don't add any complexities if you can just use a server aggregation counter or the snapshot in memory. If you need to sort or realtime updates, you are going to have to have a counter variable on a document somewhere to query. This could be updated with increments or aggregations. You may prefer Firestore Callable Functions, or you may just want to use your Form Actions API in your Framework with firebase-admin
. You may want Firestore to automatically add up everything for you in a Trigger Function, or you may want instant updates with Batching from the Client.
Ultimately there are some preferences and options for each person and use case, but you should understand all of them to know what works best for you.
J