Slack: 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 — HTTP polling + Postgres
1. Current architecture
Where we are before growth pressure
3 apps + Postgres db.r6i.large. Tables: `messages(message_id, channel_id, user_id, body, created_at)`, `channels(channel_id, workspace_id, name)`. Clients poll `GET /messages?channel_id=X&since=<last_id>` every 2 seconds. Presence tracked via last-seen timestamp updated on each poll.
2. Growth trigger
What changed — the traffic/data force
Early product. 1000 workspaces, 5-30 users each. 100K DAU total. Peak 10K RPS mostly polling requests every 2 seconds.
3. Bottleneck — what breaks FIRST?
The component that saturates as growth arrives
None yet — polling works at this scale
10K RPS at 100K DAU is manageable on single Postgres. Polling every 2s = 30 requests/user/hour = doable. p99 message delivery: 1-2 seconds (poll interval). Users don't notice at this scale.
Postgres CPU 40%, poll response latency 30ms, message-delivery lag 1-2s (poll interval), 100K DAU handling comfortable
4. Options — what could we do?
Alternatives an architect must consider before picking
- + Simplest architecture
- + No persistent connection management
- + Team ships fast
- + Firewalls/proxies work transparently (HTTP)
- − Messages have 1-2s delivery lag (poll interval)
- − Wasted requests: 90%+ of polls return 'no new messages'
- − Scales linearly with users × poll rate
- + Instant message delivery
- + Lower request volume
- − Premature complexity — connection management not needed yet
- − WebSocket infrastructure is significant investment
5. Chosen
The specific decision we're making
Do nothing — HTTP polling is right at 10K RPS with 1-2s message lag acceptable
6. Trade-offs
What we're explicitly accepting to move forward
- Accept 1-2s message delivery lag (poll interval)
- Accept 90%+ wasted poll requests
- Accept ceiling around 100K-500K DAU on polling (millions of polls/sec becomes prohibitive)
- Accept no true presence — just last-poll-time approximation
7. New architecture
The system after this decision — headroom for the next 5-10x
3 apps + Postgres. Client polls every 2s. Total cost: $500/mo.
8. Next bottleneck — what will break at the NEXT rung?
This is the seed of the next rung
At ~100K RPS with 1M+ DAU, polling generates 500K+ requests/sec (10 polls per user per minute × 100K active). Also users demand instant delivery + true presence + typing indicators — polling can't do this. WebSockets — L5 shape.
What comes next in your Junior → Architect journey
You've traced 6 rungs of Slack 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.