Skip to main content
Scale Evolution Timeline
6 rungs · 10K → 1B RPS

Twitter/X timeline: Junior → Architect Evolution

The mandated interactive flow. Step through each rung, ask what breaks FIRST, weigh the options, and defend the chosen architecture. This is how architectural thinking is learned — not by reading a fixed design, but by tracing how it evolves under growth pressure.

Back to Twitter/X timeline

Scale Evolution Timeline

Step through 6 architectural rungs, from 10K RPS to 1B RPS. At each rung, ask: what will break FIRST? Why? What options exist? Which one do we pick — and what are we accepting?

This is the reasoning cycle that separates a Junior developer ("here's an architecture") from an Architect ("here's why this architecture, why now, and what breaks next").

Rung 1 of 610K RPS
10K RPS

10K RPS — pull-based feed (read-time fanout)

1. Current architecture

Where we are before growth pressure

3 × c6i.large apps + Postgres db.r6i.large. Tables: `tweets(tweet_id, user_id, content, created_at)`, `follows(follower_id, followee_id)`. Feed generation on read: `SELECT tweets.* FROM tweets JOIN follows ON tweets.user_id = follows.followee_id WHERE follows.follower_id = ? ORDER BY created_at DESC LIMIT 20`.

2. Growth trigger

What changed — the traffic/data force

Early startup, 100K DAU, ~500 tweets/sec, ~10K feed-fetch requests/sec. Users follow ~50 people on average. Pull-based feed works because query cost per feed = 50 followees × recent-tweet-lookup = well under DB capacity.

3. Bottleneck — what breaks FIRST?

The component that saturates as growth arrives

Bottleneck component

None yet — pull-based feed is fine

Why it breaks

10K feed reads/sec × 50 followees per user = 500K row lookups/sec, well within Postgres capacity when indexed properly (composite index on tweets(user_id, created_at DESC)). p99 feed latency: 15-40ms. DB CPU 30%.

Signal you'd see

Postgres CPU 30%, feed query p99 40ms, tweets-table indexed lookups 500K/sec sustained, follow-count avg 50 (long tail: 500)

4. Options — what could we do?

Alternatives an architect must consider before picking

Do nothing — pull-based feed is right for this scale
  • + Simplest possible architecture
  • + Feed is always fresh (no cache invalidation)
  • + Deletes are trivial (deleted tweet never appears in feed)
  • + Follow/unfollow is atomic (next feed reflects new graph)
  • Feed cost grows linearly with followee count
  • Ceiling around 100K feed-fetches/sec on this hardware
$310/mo

5. Chosen

The specific decision we're making

Pull-based (read-time fanout) — right architecture at 10K RPS with 50 avg followees

6. Trade-offs

What we're explicitly accepting to move forward

  • Accept ceiling near 100K feed-fetches/sec — plan migration around 50K
  • Accept feed cost scales with follow-count — power users (500+ follows) already see 100ms+ feeds
  • Accept single Postgres SPOF for now

7. New architecture

The system after this decision — headroom for the next 5-10x

3 apps + Postgres with proper indexing. Total cost: $310/mo.

Estimated: $310/mo

8. Next bottleneck — what will break at the NEXT rung?

This is the seed of the next rung

At ~100K RPS, feed queries saturate. Users following 1000+ people see feed queries scan 10x more rows. Users open Twitter app 20-30 times/day. Push-based (write-time fanout) precomputes feeds and shifts cost from read to write — L5 shape.

What comes next in your Junior → Architect journey

You've traced 6 rungs of Twitter/X timeline evolution. Now try the same reasoning cycle on a system you don't know yet — pick from the Systems catalog and answer the same questions: current arch → growth trigger → bottleneck → options → chosen → trade-offs → new arch → next bottleneck. That is architecture.