0

I have a collection of "Chats", each of which has a number of "Threads" subcollections. (Think of Microsoft Teams, or Slack threads, or Discord threads)

Each "Thread" can have a number of replies, and I was wondering whether it was feasible to make these replies a property of the "Thread" document rather than using a "Replies" subcollection. According to the pricing table, this would reduce costs but from what I can see this would be a bad practice and testing it out has shown that it's harder to implement.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Jensen Rice
  • 57
  • 1
  • 5
  • 1
    I even wrote an article on this topic, called [How to reduce Firestore costs?](https://medium.com/firebase-tips-tricks/how-to-reduce-firestore-costs-8cb712473e83). – Alex Mamo Aug 26 '21 at 15:36
  • 1
    Cool article! I'm glad I came to a similar conclusion as someone much more knowledge than me on the subject. I'll keep the bit towards the end about sharding in mind in case I want to implement that in the future! – Jensen Rice Sep 17 '21 at 11:50

2 Answers2

1

It is, just ensure that messages use a transaction to complete as multiple writes can collide in the wrong circumstance. Additionally, including a server timestamp to maintain the order and time of creation.

Using one document does potentially limit you to ~7000-10k lines of text. Ultimately, there is no clean way of handling multiple sub comments, and you will have to use a service that best suits your needs. Personally, I prefer realtime database with a limit/orderby query and paginating comments.

DIGI Byte
  • 4,225
  • 1
  • 12
  • 20
  • Awesome, thanks for the reply. I recognized that there would be a tradeoff in maximum size of a conversation thread but since I don't think my app would often get to that thread size, I don't think it's a huge minus. (I think Slack actually has a maximum thread size) But I'm interested in different solutions/using realtime database, which is what I used for this app's prototype in college. Using realtime database, which charges by size, does sound good for numerous but tiny (size-wise) replies. I'll have to look into/think about it, thank you! – Jensen Rice Aug 23 '21 at 00:59
1

Each "Thread" can have a number of replies, and I was wondering whether it was feasible to make these replies a property of the "Thread" document rather than using a "Replies" subcollection.

This solution will work as long as the size of the document is less than 1 MiB. In my opinion, storing the replies that correspond to a conversation into an array is the best option you can go ahead with. Since the replies are always strings, you can store a lot of them, maybe hundreds, or even thousands. If you think that a single conversation might get a number of replies that is bigger than the number that fits into a single document, then try to consider sharding them over multiple documents.

Find a predictable name for each document, maybe a date or a date and time frame and that's it. You can reduce the number of reads consistently. Imagine you have 2k replies to a conversation. Are you willing to pay 2k reads instead of only one or maybe two document reads?

Storing the replies in the Firebase Realtime Database is also an option to take into consideration, as it's more suited to such smaller pieces of information, as your replies are. And indeed it doesn't have the cost of document reads. However, it will be costly in terms of bandwidth if there will be lots of replies.

So in the end it's up to you to do the math and choose which option is cheaper. If you choose to have the conversations in Firestore and the replies in the Realtime Database, please note that both work really well together.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Sorry, haha, hadn't realized that my inbox had the notifications on it. Thank you for the knowledgeable response! I'm going with storing replies in the conversation because of the costs reasons you mentioned (loading a ton of replies would be costly), but actually as an object and not an array. Now I'm wondering if I should change it to an array haha. As I have it right now I'm storing all my messages in a both in a "Messages" collection and using that uniqueid as the key for them in the Replies object. – Jensen Rice Sep 17 '21 at 11:39
  • 1
    Check the payments in the next period. If you'll encounter many reads, move those objects to an array, and read only a single document ;) – Alex Mamo Sep 17 '21 at 12:04
  • 1
    It's all in the conversation object still, just as an object and not an array (the key is the key created in the "Messages" collection which won't be read often - may remove this collection at some point but it's to find messages by user so a user could view all their recent activity in one place). I'm actually not in production, this a project I'm trying to complete in my free time so I don't have much for costs. I actually just starting rewriting stuff to use a array rather than an object since it does just make more sense and will be easier to deal with! – Jensen Rice Sep 17 '21 at 12:19
  • Good to hear that. Good luck with that. – Alex Mamo Sep 18 '21 at 08:08