Free preview

Requirements

In one line: the consistency requirement here is the best-stated one in any problem chapter so far, and the scalability requirement contains a ratio worth checking rather than repeating.

Functional requirements

RequirementDetail
Post tweetsUsers can publish messages containing text and media
Delete tweetsUsers can remove their own content
Like or dislikeUsers can engage with tweets by liking or disliking them
ReplyUsers can reply to public tweets
SearchUsers can search for content using keywords, hashtags, or usernames
View timelinesHome timeline (tweets from people they follow) and user timeline (their own tweet history)
Follow or unfollowUsers can follow or unfollow other accounts
RetweetUsers can share other users' public tweets

Two timelines, and they are completely different problems

"Home timeline (tweets from people they follow)" and "user timeline (their own tweet history)" are listed as one requirement. They are not remotely equivalent.

User timeline is trivial: fetch tweets where author_id = me, ordered by time. One index, one query, one author. It is a simple range scan.

Home timeline is the hardest thing in the chapter: merge the tweets of everyone I follow, ranked, paginated, in real time. If I follow 500 accounts, that is a 500-way merge — on every refresh, for every user.

That asymmetry is the entire fan-out problem, and Lesson 5 takes it on. Notice it is completely invisible in the requirement as written.

When one requirement bundles a trivial case with a hard one, separate them before you design. A candidate who says "timelines are a range scan" has answered the easy half and missed the chapter.

Delete is harder than post, and the requirement list hides that too

"Users can remove their own content" is one line and it is the most awkward operation in the system, for a reason that will only become clear after Lesson 5.

If timelines are precomputed — the tweet copied into millions of followers' feeds at post time — then deleting it means finding and removing millions of copies. Compare posting, which is one write plus an asynchronous fan-out.

And the copies are not the only problem. A deleted tweet may already be in the search index, in caches at multiple tiers, on CDN edges, and retweeted by others.

Real systems mostly resolve this with tombstones rather than deletion: mark the tweet deleted in one authoritative place, and have the read path filter it out. That converts an expensive scatter-delete into a cheap write plus a check on read.

The cost is that every read now pays a filtering step, and the data physically persists until compaction. Which is the usual shape: deletion in a fan-out system is a read-path problem, not a write-path one.

Non-functional requirements

RequirementDetail
AvailabilityTwitter is often used for time-sensitive communication during emergencies, so uptime is critical
LatencyLow latency to deliver feeds. Complex feed generation can run asynchronously, but the user's read path must remain fast
ScalabilityRead-heavy, with an estimated 1:1000 write-to-read ratio. Must scale computationally and provide massive media storage
ReliabilityData durability is essential. Uploaded content must never be lost or corrupted
ConsistencyEventual consistency for the global view — but immediate feedback to the user acting

The consistency requirement names both halves correctly, which is rare

Read it carefully:

"We can accept eventual consistency for the system's global view. For example, a user in the US East region might see a tweet slightly before a user in the US West. However, the system must provide immediate feedback to the user acting (e.g., a user must see their own like or reply instantly)."

This is read-your-own-writes, stated precisely, and it is the first problem chapter to get it right.

Compare that building block, whose evaluation claimed "users have a consistent view because we use fault-tolerant databases" — a non-sequitur. And that building block, which credited synchronous replication with delivering both availability and consistency.

Here the two halves are correctly separated:

ScopeGuaranteeWhy
Everyone else's viewEventualNobody can tell whether a tweet arrived 200 ms earlier in another region
Your own actionsImmediateYou know you pressed like — if the count does not move, the app looks broken

The asymmetry exists because you have out-of-band knowledge of your own actions and none of anyone else's. That is the entire justification for session-level guarantees, and it is why that building block's session guarantees — read-your-writes, monotonic reads — are the practically useful consistency models rather than the theoretical extremes.

The implementation is usually cheap: route a user's reads to the replica that took their write for a short window, or have the client optimistically render its own action while the write propagates.

Say "eventual consistency with read-your-own-writes" rather than picking one. It is more accurate and it demonstrates you know consistency is scoped to a session, not to a system.

The 1:1000 ratio does not match the course's own Twitter numbers

"Read-heavy, with an estimated 1:1000 write-to-read ratio."

The direction is certainly right. The magnitude is worth checking, because our Foundations chapter works the same service:

Tweets posted     = 1.5B/day  / 86,400  =  17,361 writes/second
Tweets viewed     = 500M x 50 / 86,400  = 289,352 reads/second
                                           -------------------
Actual ratio                            =  about 1 : 17

To reach 1:1000 you would need 17.4 million reads per second, sixty times the figure the estimation produces.

So the two numbers are measuring different things, and reconciling them is instructive. The most likely reading is fan-out amplification: one posted tweet is not one read but one delivery to every follower's timeline. An account with 1,000 followers generates 1,000 timeline insertions from a single write.

That reframes the ratio usefully. 1:1000 is not the ratio of user actions — it is the amplification factor of the fan-out, and it is a statement about the write path rather than the read path.

Which makes it far more interesting than a read-heavy claim. It says: a single write can cost a thousand operations internally, and that is precisely the design tension Lesson 5 resolves.

If you quote the ratio in an interview, say what it counts. A ratio without units is a number you have not checked.

The latency requirement pre-authorizes the whole architecture

"Complex feed generation can run asynchronously, but the user's read path must remain fast."

One sentence, and it licenses nearly every decision in the chapter.

It says: you are permitted to do expensive work, as long as the user is not waiting for it. Which means:

  • Fan-out can happen after the tweet is acknowledged (Lesson 5).
  • Search indexing can lag behind posting (Lesson 7).
  • Counter aggregation across regional shards can be delayed (Lesson 10).
  • Analytics through Kafka and Dataflow are entirely off the request path (Lesson 6).

That is the same materialize-versus-compute trade as that building block's precomputed paths and that building block's asynchronous billing — but stated here as an explicit requirement rather than discovered as a technique.

Requirements that say what may be slow are as valuable as requirements that say what must be fast, because they tell you where to move work.

Building blocks

BlockRole
DNSMaps domain names to IP addresses
Load balancersDistribute read and write requests
SequencersUnique, time-sortable IDs for tweets — Twitter's Snowflake
DatabasesTweet and user profile metadata
Blob storesImages and videos
Key-value storesIndexes, caches, user-specific data
Pub-subAsynchronous processing and real-time updates
Sharded countersHigh-volume counts for popular accounts, preventing write contention
CacheFrequently accessed data in RAM
CDNStatic content closer to users
MonitoringTraffic, failures, system health

Time-sortable IDs are doing more work than the one-line description suggests

"Sequencers: generate unique, time-sortable IDs for tweets" — Twitter's Snowflake, covered in unique ID generation.

The time-sortable property is the interesting half. A tweet ID that sorts by creation time means:

Timelines need no separate sort key. Ordering by ID is ordering by time, so a range scan returns tweets in order for free.

Pagination works without offsets. "Give me tweets older than this ID" is a range query, which is why the API's next_token in Lesson 4 can be a cursor rather than an offset — and cursors do not break when new tweets arrive mid-pagination.

IDs are generated without coordination. Snowflake encodes a timestamp, a machine ID, and a sequence number, so every node mints IDs independently and they still sort correctly globally.

That last property is why this matters at all. A globally-ordered sequence that needs no global coordination is a genuinely hard thing to get, and it is what makes distributed timeline assembly possible.

Key takeaway

The two timelines are different problems — a user timeline is a range scan, a home timeline is a 500-way merge — and the requirement bundles them. Delete is harder than post in any fan-out design, which is why real systems use tombstones and pay on read. The consistency requirement is the best-stated in the course: eventual globally, read-your-own-writes for your own actions, because you have out-of-band knowledge of what you did. The 1:1000 ratio doesn't match the course's own figures (~1:17 on views) and is best read as fan-out amplification — a statement about the write path. And "feed generation may be asynchronous" is a requirement that pre-authorizes the entire architecture.

Next: the estimation this chapter declines to do.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue