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.
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").
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
None yet — pull-based feed is fine
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%.
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
- + 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
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.
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.