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

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.

Back to Slack

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 — 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

Bottleneck component

None yet — polling works at this scale

Why it breaks

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.

Signal you'd see

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

Do nothing — polling is fine at 10K RPS
CHOSEN
  • + 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
$500/mo (3 apps + Postgres)
Preemptively add WebSockets
  • + Instant message delivery
  • + Lower request volume
  • Premature complexity — connection management not needed yet
  • WebSocket infrastructure is significant investment
$2K/mo

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.

Estimated: $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.