DAU - 0.5 billion
messages per user - 50
average text payload - 1KB
Storage day - 0.5*10^9 * 50 * 1KB = 25TB -> 25*365 = 9PB year
Bandwidth - 25GB/(24*60*60) * 8 = 2.3Gbps
QPS - 0.5*10^9 * 50 / (24*60*60) = 290k/sec
Server - 0.5*10^9/64k = 7812 servers for peak load
POST /api/v1/{conversation_id}/message
{
auth_token,
text
}
POST /api/v1/messages/{msg_id}/ack
{
auth_token,
message_id
}
GET /api/v1/{conversation_id}/messages?offest&limit - returns
[message_ids]
GET /api/v1/messages/{msg_id} - returns
{
text
}
POST /api/v1/presence/heartbeat
{
auth_token
}
GET /api/v1/presence/{user_id}
users table SQL
{
user_id,
name,
email,
}
conversations table NOSQL
{
conversation_id,
user_id1,
user_id2
}
messages table NOSQL
{
pk: conversation_id,
sk: sequence_id,
}
acks table NOSQL
{
conversation_id
msg_id,
user_id,
}
presence table NOSQL
{
user_id,
websocket_server,
last_seen: timstamp
}
unread message queue table NOSQL
{
conversation_id,
msg_id,
receiver_id
}
load balancer - used to distribute messages accross servers.
api gateway - used to authenticate, authorize, and route requests.
Chat service - used to process user message requests.
presnece service - used to check whether user is online and to which websocket server it's connected to.
Kafka - event storage to separate message events from critical path.
Notification service - send receiver the message if he is online and store the message in a queue.
Send message flow:
receiver acknoledge message as read:
Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?