500M ADU, create one post per day, read 10 pages on home page per day, like 5 posts per day. Assume each user follow 100 users.
Write: 500M/10^5 = 5k TPS
Read: 10 * 5k = 50k TPS
Storage:
150b * 500M = 75GB/day = 27TB/year
Query pattern:
User table
Post
Follow
Favorite
All the requests go through a load balancer to App server. To scale, we can separate read requests from writes. The read servers handle read post requests while the write servers deal with all post creation/favorite, user sign up etc.
The data is saved to redis and database.
A count service scan through the database every 5 min to calculate the number of likes for each post.
Redis
Get home page is the feature that creates the most traffic. To speed up the process, we use redis to cache the data.
Count service
The num_of_like in the Post table might become a bottleneck if we do real-time calculations. If we don't do calculation, we have to lock the row when a post is liked by others. To solve that, we dedicate a separate service to do the calculation async.
For hot users, fan out might be inefficient due to the huge number of followers. We can cache a list of celebrities in redis, when creating home timeline for user A, we check if s/he follows any celebrities, if so, fetch the latest posts from the celebrity's user timeline and add those along with the home timeline lists.
If we want to notify the users with new posts available from the users they follow, we can connect the user with the read app server via websocket to allow bi-diretional communication. Then we add a message queue for each user in the flow. Once a new post is created, the post is published to all the followers' queue, the read server then pushes a notification to the user's device on new posts available.