500M users/day. Each writes 2 tweets = 1B tweets/day / 10 hours = 100M/h / 100 min = 1M/m / 100s = 10k tweets per second authored.
Each users checks feed 10 times per day = 50k feed gets per sec.
Each users favorites 20 times per day = 100k favorites per sec.
Each user checks favorites 1 time per day = 5k favorites list per sec.
PUT /publishTweet
{
text: string
}
GET /feed?before=timestamp
PUT /favorite?tweetId=int
GET /favorites
Tweets:
FavoritedTweet:
Users:
UserFollow:
We will have a web tier to handle the HTTP requests from the clients. It will have a load balancer. We use a relational database to store tweets, favorites, and users, because joins are helpful for listing favorited tweets, and also we may want to do different types of queries in the future. We shard the database by user and replicate it. We have a queue that subscribes to the tweets table. Feed service reads from the queue to assemble a feed for the users. It has a feed cache so the feed for a user can be served quickly. If more tweets are requested than is in the cache, it checks the database for posts from users that the user has followed.
Assembling a feed can be complex. We want to prioritize tweets from the people the user followed, and also more recent tweets. This can be done using where clauses in the SQL query. It can also be expensive to cache feed for users that are not active in the past week or month, so we can have the feed service ignore those from the queue.
This architecture makes the assumption that most users will not be constantly refreshing feed very frequently. If there is too much cache miss in the feed service then the database may get overloaded.
If there is too much cache miss in the feed service then the database may get overloaded.
We can have a separate nosql database for storing feed, so that the cache miss is not as impactful.