- allow users to send messages to their friends
- allow users to send to non-friends too
- messages need to be stored
- messages need to include time stamps
- messages need to be able to be deleted for one user or both
- need to allow for group chats
- session needs to stay logged in for user's device
Performance:
- messages need to be sent in close to real time
Availability:
- service always needs to be available, even if messages are not propagated right away
- eventual consistency is ok
Security
- communication needs to be end-to-end encrypted
- users need to have a Facebook account
- need to track logged in devices (probably with IP address), so main user can log out hackers
Scalability
- use a NoSQL database, since these prioritize availability and eventual consistency
- use a graph database. our service is a social network by nature, so we can connect complex relationships
- have a load balancer using the IP hash LB algo. This algo takes the client's IP address, hashes it, then the LB determines which server to use based on the hash
- facebook is worldwide, so using geolocation makes the most sense with load balancing
- similarly, we should shard our database based on region. For example, we can have a cluster of shards for US, another for India, etc.
- we should rate limit how many messages a user can send at the same time to not overload servers
- need to have high concurrency
- denormalize the database, since denormalizing improves read performance at the expense of write
- denormalize means combining or duplicating data to optimize for read-heavy workloads
- since we are using a graph database, we will have extra relationships between nodes to prevent more expensive traversals
- utilize cache on user's device to cache the latest retrieved messages
- master-slave replication for each shard
5-10 million daily users
10:1 read to write ratio
/sendMessage (this can be for one to many recipients)
(session token, recipient: array of recipients, message):
call /validateSession
call /getUser
if there is a relationship, just create a new relationship on top of the existing one between sender and receiver(s).
else, create a new relationship between sender and recipient(s).
the new relationship should be from sender to recipient(s), and its values should be UUID, timestamp and the message text. If there are multiple recipients, this relationship should also include a boolean for group chat value
return the object
/seeAllMessages
(session token)
call /validateSession
call /getUser
check cache for all messages
see if any of the relationships were updated
get most up to date chats
update cache
update on user device
/deleteMessage
(session token, array of recipients, message)
call /validateSession
call /getUser
get message UUID
find any relationships between nodes that match UUID, remove those links
/leaveChat
/validateSession
(session token)
get sessionID from token
ensure sessionID matches active session
ensure IP address matches that active session
/getUser
(session token)
get session ID from token
returns the userID associated with the session ID
session node:
sessionID UUID
start_time DATETIME
end_time DATETIME
ip_address string
device_type string
status string
user:
userID UUID
first_name string
last_name string
email string
device:
deviceID UUID
device_type string
os_version string
chat:
chatID UUID
start_time DATETIME
end_time DATETIME
status string
message:
messageID
send_time DATETIME
text string
user -> hasSession -> session
session -> fromDevice -> device
session -> hasChat -> chat
userA <-> hasChat <-> userB
userA -> hasMessage -> userB -> hasMessage -> userB> hasChat -> userA
You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
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...
Chose to use NoSQL database because with a social media messaging service, we prioritize availability over consistency. It is ok if the data is stored in the database eventually.
We chose a graph database because relationships can get complex with social media platforms. Graph databases allow for flexible relationships between nodes.
If the system fails before primary shard is copied to its backup, data can be lost
If the primary goes down before the message is even saved to the primary, also a potential loss of data.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?