can send both text and media
both 1-1 and group chat, user can add members to group chat, change group name, update retention policy, delete messages
both web and mobile client
sort the feed based with conversation with unread messages first and then last read timestamp
very low latency with p50 on single digits on sending messages
when sync the feed and messages, clients only sync the new content since the last time it syncs
100M DAU
each user sends 10 messages per day
online api
// send new messages
send(destinations []Conversation, content string, ttl long)
// delta-sync the chat feed
syncFeed(userID)
// delta-sync the conversation
syncConversation(conversationID)
// create a new conversation
createConversation(conversationID, conversationMetadata)
// updateConversation
updateConversation(conversationID, conversationMetadata)
// deleteConversation
deleteConversation(conversationID, conversationMetadata)
deleteMessage(conversationID, userID, messageID)
// offline api
sendNotification()
user table
userID uuid
username string
createdAt long
privacySetting enum
notificationSetting enum
friendship table
key(uuid/uuid): fromUserID/toUserID
friendType num
lastUpdateAt long
feed table
primary key: userID
secondary key: conversationID
lastUpdateAt: long(local secondary index)
conversation table
two type of rows
message
primary key: conversationID(uuid)
secondary key: messageID(long)
createAt: long
lastUpdateAt: long(local secondary index)
retentionPolicy enum
senderUserID uuid
messageContent []byte
conversation metadata
primary key: conversationID(uuid)
secondary key: special const
createAt: long
lastUpdateAt: long(local secondary index)
retentionPolicy enum
name: string
CDN to cache media
cloud object storage to persist raw media
api gateway
chat gateway(support both web and mobile protocol), in order to directly route message from the sender to the receiver and also send notification in real-time
backend application which handles
worker service responsible for sending notification
Sync
Send
Deltasync on Feed/Conversation table
client sync token: last synced timestamp
Select * from Feed where primary_key = user_id and last_update_ts > feed_token
this will return only the feed items which have changed since the last time sync from servers.
Select * from Conversation where primary_key = conversation_id and last_update_ts > convo_token
this will return only the changed items in the conversations: new/updated messages or participant data
On write path, in order to properly update the sync token, we need to add a special row which maintains the global max of all the last updated timestamp belonging to the same user feed conversation. That means every time will do a read-modify-write on that single row.
Chat gateway routing
chat gateway is only one way from server to sender without direct connecting two clients. This sacrifices latency but can better guarantee consistency. Messages directly sending between two clients might have the issue that messages are delivered but haven't yet persisted on server or the persistence step fails. Then we need to add additional logic handling the failure. This will also impact the order of messages.
Delta Sync
This is a complicated feature which requires enabling txn on each write. But this will save huge amount of network bandwidth if we can only return delta information instead of pulling all messages.
Contention on writes
since chat app is a very write intensive app, we didn't add the cache layer. there might be an issue to support conversations with large groups(>100).
Cold Start
on the first time open app(or initial sync without local cache/sync token), users will fetch tremendous amount of data. We need to paginate in this scenarion
add e2e encryption
regionalization so that users in different geo location can requests local servers
split the backend application into smaller micro services: user service/friend service/chat service/notification service
other offline tasks, check the message deletions/send scheduled events notifications/listen to other deletion events