Designing Facebook Messenger


 Functional Req

  • One to one or groups chatting

  • Receipts / Statuses

    • Online/Offline

    • Sent

    • Delivered

    • Read

  • Multimedia Sharing

  • Security

Capacity Estimation 

500M daily active users, average each user sends 40 messages daily = 20B daily messages


Storage

A message ~100 bytes * 20B = 2TB/day. 

in 5 years : 2TB * 365 days * 5  year = 3.6PB

We need to scale. 


Bandwidth:

2TB everyday data per second : 2 TB /  86400 sec ~= 25 MB/s

High throughput we can scale.

High-Level System Design



Logic Flow


Heartbeating 


UserA goes to load balancer.  LB will pick one the host behind based on load average or number of connections.  LB picks N1 - App server. Web socket connections bi-directional nature both server and the client can initiate a request. 


At this point, while the UserA is not sending any data. They are just heart beating between them. 

Why do we need to constantly heartbeat? Because the server knows that User A is still there and also User A knows the N1 - App server still there. 


We can store this relation in the cache (Redis). No need to store DB for heartbeat data. 


User     | Server | Heartbeat Time

User A   | N1       | T1

User B   | N2       | T2


Redis is a distributed cache. It holds all the data in memory. We can multiple 3 at least every tier.  Write and read super fast from the cache. 




N1 - App server die? 

Websocket connection will incentive break. User A will know that the other end of the server died. It will initiate a new connection with the new server and the N1 App server is going to update Heartbeat information. 


If User A dies or inactive or offline?

It stops heart beating with N1 - App server then N1- App server start to update heart beating data. 

This data provides some notification on the client-side. Like this user online at 5 minutes ago or one hour ago. All this information retrieved from Cache- redis using last time heart beating data. 


Messaging Handle


  • User A friends of User B. User B is also online 

  • User A sent to message N2 - App Server that let’s say “Hi”.

User A  ---> “Hi” ----> User B

  • For the high throughput, sends a message to an in-memory message queue with the user, server, and message information. Q can store this data to the DB this message. 

  • In-memory tier sends back ‘sent’ notification to User A.

  • Task threads send back the message to the app server based on each receiver session.

This logic in Queue can check who is managing user B to check the Cache - Redis.

User     | Server | Heartbeat Time

User B   | N2       | T2

N1    --- >   N2 

And N2 App server sends this message back to UserB

  • N2 App server sends the back status of delivery.

  • User A will update the status ‘Delivered’

  • We can store persistent DB all these processes through the Message Queue.



Offline to Online Process


User A wants a message to User C. But User C is offline that now. 

User A --- > “Hi C”  ---> User C

No entry in the Redis cache about User C. User C is offline no one is managing that. 

Just write messages to the DB which could be the “Unread Messages” table by using message Queue.

When User C  does come online, whoever is managing user C let’s suppose N3 - App Server. 

App server will update to the cache. 


User     | Server | Heartbeat Time

User A   | N1       | T1

User B   | N2       | T2

User C   | N3       | T3


We know who is managing User C > N3. N3 App server starts the same process. It requests the Messaging Queue and getting Database “Unread Messages” relative data about the User C. Then N3 App server going to transmit all that information to User C.

We can remove from “Unread Messages” and we can write to the  “Read Messages” table.




Encryption


We need to encrypt all content in our messaging system. 

We have a master key in our applications. We should encrypt using this master key all content. 

And every message should be store encrypted key in the DB or cache. 






Media Sharing like Picture


Let’s say User A sends User B a picture by the same encryption.


N1 App server gets the request then we can add a new queue to send N2 App Server.

This picture in the Blob Storage in an encrypted format which is encrypted User A has the key. 

And we can store this original Url in our DB  in the “Conversation Table”.

The same process gets a heartbeat where is the User B Server. 

N2 Server will send just a thumbnail image and original URL to User B.

The original picture could be 5 MB, but the thumbnail just could be 5 kb.

Thumbnail would see in User B. If User B click this thumbnail we will take this URL and download the entire picture for the user B. But the image comes together encryption. But our encryption key help of this see this picture. 




Comments

Popular posts from this blog

Design a notification system

NETFLIX HIGH-LEVEL SYSTEM DESIGN

URL Shortener System Design