Free preview

The Complete Flow

In one line: the components have been described one at a time. Assembled, the architecture shows a division that none of the individual lessons state: three completely different read paths.

The routing

Routing: the local DNS resolves the user's request to the nearest load balancer.

Service handling: the load balancer routes the request to the appropriate service.

ServiceHandlesDetail
Tweet service (write)/postTweetAttachments to blob store. Text and metadata to Manhattan, MySQL, Vertica. Kafka pipelines process real-time data for deduplication and aggregation via Cloud Dataflow, then BigQuery and Bigtable
Timeline service (read)/viewHome_timelineChecks the CDN for static data. If not found, fetches Top-k tweets from storage and aggregates interaction counts from sharded counters
Search service/searchTweetQueries Apache Lucene — RAM index for real-time results, disk index for historical — ranking by time, location, and relevance

Infrastructure support: Zipkin traces requests for performance monitoring, while ZooKeeper maintains configuration, synchronization, and naming registries.

Three services, and the two read paths have nothing in common

Assembled, the striking thing is that timeline and search are both reads and share almost no machinery.

Timeline readSearch read
Answers"What's new from people I follow?""Who said X?"
InputA user IDA query string
IndexPrecomputed timeline (Lesson 5)Inverted index (Lesson 7)
StoreManhattan plus sharded countersLucene, RAM and disk tiers
FreshnessFan-out lagStreaming index lag
Result setBounded — the next 20Unbounded, capped at 3,200
RankingRecency, engagementRelevance, time, location

They are two different systems that happen to store the same tweets.

That is worth stating because it is the practical meaning of polyglot persistence from Lesson 6. The justification is not "different data needs different stores" — the data here is identical. It is that different questions about the same data need different indexes, and an index is a commitment to one access pattern.

Manhattan answers "give me tweet 12345." Lucene answers "give me tweets containing 'earthquake'." Neither can do the other's job efficiently, so the same tweet is written to both.

When one dataset must answer structurally different questions, you maintain multiple indexes and pay the write cost. That is Lesson 3's amplification, seen from the other end.

The write path is one synchronous step and several asynchronous ones

Trace /postTweet against Lesson 2's "complex feed generation can run asynchronously":

SYNCHRONOUS  (user waits)
  validate, mint a Snowflake ID, write to Manhattan, media to blob store
  -> acknowledge

ASYNCHRONOUS (user does not wait)
  fan out to follower timelines        (Lesson 5)
  index for search                     (Lesson 7)
  publish to Kafka -> Dataflow         (Lesson 6)
  extract hashtags for trend counting  (Lesson 10)
  notify tagged users                  (Lesson 4)

One durable write is acknowledged; five downstream effects proceed independently.

That structure is what makes the amplification from Lesson 3 tolerable. One tweet becoming hundreds of internal operations would be unacceptable if the user waited for them; off the request path it is merely capacity planning.

It also sets the failure semantics. If fan-out fails, the tweet still exists — it is stored, and it will appear in timelines when the job retries. Compare a synchronous design, where a fan-out failure would fail the post.

Acknowledge on durability, propagate afterwards. The general rule for any system with heavy write amplification, and the same conclusion that building block reached about payments and that building block about billing.

'The request first checks the CDN for static data' is doing very little

The timeline description says the request "first checks the CDN for static data. If not found, the timeline service fetches Top-k tweets."

Be careful about what a CDN can actually serve here. A home timeline is unique to one user — it is the merge of the accounts they follow — so it is not cacheable at the edge in any meaningful sense.

What the CDN genuinely serves is what Lesson 3's estimate said dominates the bytes:

CACHEABLE AT EDGE:      images, video, avatars, static assets   <- 88% of egress
NOT CACHEABLE AT EDGE:  the timeline itself                     <- per-user

So the CDN is not accelerating timeline assembly; it is serving the media referenced by the timeline. Which is exactly right and hugely valuable — Lesson 3 put media at 347 Gbps of 394 — but it is a different claim from the one the sentence implies.

And Lesson 4 gave a further reason the timeline itself cannot be edge-cached: promoted tweets are selected per request, and protected-account visibility must be checked per reader. Personalized content cannot be cached at a shared edge, which is why the CDN story here is entirely about media.

ZooKeeper and Zipkin are drawn beside the flow, not inside it

Both appear as "infrastructure support" rather than as steps, and the placement is correct.

ZooKeeper is on the control path — configuration, service registry for Lesson 11's client-side balancing, Manhattan's cluster topology. Consulted to learn where things are, not to carry requests. Lesson 11 made this the crux: moving a dependency from the data path to the control path converts per-request cost into per-change cost.

Zipkin is beside the path — sampling a small fraction of requests, per Lesson 9. If it fails, requests still succeed.

That is the right relationship for both, and it generalizes: infrastructure that observes or configures should not be able to fail a request. A tracing system that took requests down would be worse than no tracing; a configuration store on the data path would be a bottleneck and a failure domain.

The test is simple. If this component is unavailable, can users still use the product? For ZooKeeper the answer is yes for a while, because clients cache topology. For Zipkin it is yes indefinitely. For Manhattan it is no — which is why Manhattan is in the flow and these two are drawn alongside it.

One write, three fan-outs — into timelines, into the search index, and into the trend stream. They share nothing downstream, which is why each can fail, scale, and be reasoned about independently.

Key takeaway

Assembled, the architecture's real division is two read paths with nothing in common — timeline and search store the same tweets and share no machinery, because different questions about the same data need different indexes, and an index is a commitment to one access pattern. The write path is one synchronous durable write plus five asynchronous effects, which is what makes Lesson 3's amplification tolerable and which sets the failure semantics: acknowledge on durability, propagate afterwards. The CDN serves media, not timelines — a personalized feed cannot be edge-cached, especially once ads and per-reader visibility are involved. And ZooKeeper and Zipkin sit beside the flow because infrastructure that observes or configures should never be able to fail a request.

Next: the whole design under interview conditions.

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