User visits facebook.com. Gets home feed.
User follows another user.
User follows a page (specific topic).
On user's newsfeed, user will see:
Response time. After user visits the page, newsfeed should appear within 0.5 second.
Client can be a browser or a mobile app.
Availability.
Scalability. Increasing data e.g. videos and images.
We can relax a little bit on consistency. E.g. if one user sees a post at time 0, but another one sees the same post seconds later, that'd be acceptable.
Key Points:
System receiving huge amount of media files (videos and images), while maintaining short response time for users.
DAU: 500M users
Each user accesses homefeed twice a day
Each user posts a status update, image or video once a day.
Data:
Video: 10MB
Image: 1MB
Status update: 1KB
500M / 3 * 10MB = 1.7PB / day
Key observations on data:
For relationship, write path is follows APIs.
User profile - 2KB
2B users.
4TB data
Document based NoSQL, e.g., MongoDB, would be a good choice. It has configurable consistency models. Compared to RDB, it would allow us to be more horizontally more scalable. It would be possible to trade ACID consistency for scalability and performance.
RESTful API.
follow_user(follower_user_ID, followed_user_ID)
follow_page(follower_user_ID, followed_page_ID)
get_newdfeed(user_ID)
upload(user_ID, media_content)
post_update(user_ID, update_content)
Essential parts of data models:
User:
Post:
Page:
# this is a join table which represents the posts made by user
User_Post:
# this is a join table which represents the posts made on a page
Page_Post:
Newsfeed Service will use the tables above to create feed. For example,
select Post_ID from User_Post where User_ID in (N users user is following) and timestamp (last 24 hours)
and aggregate the posts with some heuristics, e.g.,
score(post) = weight1 * recency + weight2 * popularity_of_followed_user + weight3 * number_of_likes_on_post
We would store some of this calculation in cache, so that Newsfeed Service does not have to do this query and calculation on every request.
Tracking recent posts by a user
{
User_ID: ,
Posts: [
Type: text/image/video,
Text: text content of status update,
URL: URL pointing to the media file
]
}
Media will be a parent URL. E.g. "https://sth.facebook.com/media/0123". Media Service will use this as a key to look up child URLs that contain media in different format and quality, e.g., http://sth.facebook.com/media/0123_480x320_mpeg or something like that.
Write flow:
Read flow:
{
user_ID,
timestamp: ,
[
type: text/image/video,
text: text content
URL: links to image/video
]
}
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?