Peak maybe 10x ~ 600k messages/sec
Chat history
Get /chats/{id}/messages
Chat list
Get /chats
Group APIs
Create group
POST /groups
Add member
POST /groups/{id}/members
Update group = disable/delete
PUT /groups/{id}
gRPC - for sending/delivering real time messages to group or single user
sendMessage(from, to, text)
Joining chat - via websockets. when user opens app a new websocket connection is created so user can recieve message (via chat Service using the active socket connection
Backed by Redis.
Stores:
userId → set(deviceId, gatewayId)Used for:
Responsible for:
👉 Single source of truth for message ordering
Consumes MessageCreated events:
Stores lastRecievedSeq in redis after delivery attempt
👉 Best-effort real-time delivery only
Triggered on reconnect:
Consumes Kafka events:
Manages:
Handles:
conversationId used as partition keyWe use a NoSQL store (e.g., Cassandra / DynamoDB-style model) optimized for:
Data is modeled around access patterns, mainly:
Data Models
conversationId (partition key)sequenceNumber (ordering key)messageIdsenderIdcontent (encrypted)createdAt👉 Messages are stored append-only per conversation and strictly ordered by sequenceNumber
conversationIdtype (1:1 / group)createdAtlastMessageSeqstatus👉 Used for chat list + quick access to latest message
conversationIduserIdrolejoinedAtstatus👉 Defines group membership
userIdconversationIdlastReadSeqlastDeliveredSeq👉 Tracks read/delivery state efficiently (instead of per-message status)
We will now deep dive into:
Approach:
conversationIdChat service assings to a message:
Implementation Option:
Ordering is guaranteed by Kafka partitioning + monotonic sequenceNumber in DB
Steps:
Solution:
Optimization oppurtunities:
Problem: Millions of active users = millions of connections, so scaling is ciritical
Actual Scaling:
Failure handling: