messages one on one
message:{
messageId:string;
messageFrom:string;
messageTo:string;
createdAt: Date;
content:string;
}
messages to groups:
message:{
messageId:string;
groupId:string;
userId:string;
createdAt:string;
content:string;
}
GET /messages shows a preview of the latest message with the last few users to the active user
GET /messages/user/{userId}?since={since} shows messages with a user since a date
POST /message/user/{userId} body:{content:string} sends a message to a user
GET /messages/group/{groupId}?since={since} shows messages within a group since a date
POST /message/group/{groupId} body:{content:string} sends a message to a group
POST /group/manage body:{userIds:JSON, groupName: string} - creates/edits a group with multiple users
POST /group/manage body:{userIds:JSON} - adds multiple users to a group
POST /group/{groupId}/manage/remove body:{userIds:JSON} -removes users from group
POST /group/{groupId}/manage/disable - disables a group
POST /connect -sets current user as online
POST /disconnect - sets current user as offline
POST /heartbeat - sends a heartbeat to check if a client is still online
POST /subscribe/user/{userId} - subscribes the current client to a user conversation
POST /subscribe/group/{groupId} - subscribes the current client to a group conversation
messages are received through websockets
sending 1 on 1 messages flow:
sending messages in a small group (<500 members):
creating/managing groups flow:
we could add rate limiting on chat servers so we dont allow users to send more than 5 messages per second. we could implement token bucket algorithm and if the user exceeds the number of requests, we will postpone them for the next refill (next second)
for managing servers we could use zookeeper; for authenticaton, the user will log in and from then on, on each request it will send a jwt token
messages are pushed to online users through websockets
if the users are offline, they receive push notifications, if they dont have internet connection, the message is saved in the db, and in the sync queue and whenever they come back online, the message is retried
when sending messages to a large group, user makes the call which reaches chat server and pushes the message to a pub sub system like redis, then it will use websockets to forward to users the messages
for sending attachments, we will separate the paths, we'll save to s3 the attachments and the plain text will be sent directly, whilst media will take longer because it must be uploaded to s3 too
regarding backpressuer: we will monitor queues and when they reach 85% we increase their number and scale out
Caching is advisory, not authoritative. Messages are always written to the database first, then cached in Redis sorted sets keyed by conversation ID with timestamp as the score. This guarantees ordering. On read, cache misses fall through to the database. Stale cache entries are acceptable since the client deduplicates by messageId and sorts by timestamp. Presence and group membership use short TTLs (30sā5min) with invalidation on state changes.
each component is isolated, during outages there is no single point of failure, if one service fails, a slave one will take its place, if the queue fails, when it comes back online it will still have its messages cause they are stored on disk; if a consumer fails, the message still remains in the queue and can be reprocessed
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.