Problems / Real world, hard
Slack as first built: channel history read straight from MySQL with no cache, no read replicas, and the message, history and presence services, fan-out workers and search at an eighth of their real size. 5,000 requests a second: 45% reading history, 40% sending messages that fan out to channels, search and push, 15% presence. Messages and history time out.
Unlock it once for 25 credits; everything inside it is free (runs, changes, Submit, results, hints). Sign in with Google to start; new accounts get free credits.
Grow it into the real architecture: every goal must hold at 5,000 requests a second. You may add components, connect them and resize anything.
Like a coding problem, a solution has to pass every case, not just the one it was built for. Submit in the lab runs all 6; 2 of them are hidden until then.
5,000 requests a second for 20 seconds: 45% reads, 40% send (writes), 15% presence (writes).
What each component does in this design, and what calls it. The simulator mimics each one from these settings.
| Component | Its job here | Settings |
|---|---|---|
| DDoS protectionDDoS protection | Traffic enters here.Calls API gateway.Volumetric floods are absorbed at the network edge, spread over many locations, before they reach you. | 100000 slots |
| API gatewayAPI gateway | DDoS protection forwards to it.Calls History API, Message API, Presence API.Gateways centralise auth, rate limits and routing so each service does not reimplement them. | 50000 slots · 1,200,000 calls/min |
| Message APIApp service | API gateway forwards to it for /send.Calls Messages (MySQL, sharded by workspace), Message events (Kafka) (publishes).Little's law: throughput ≈ concurrency ÷ latency. 200 slots at 50 ms serve about 4,000 req/s. | 1 replicas × 100 slots · timeout 1.0 s |
| Messages (MySQL, sharded by workspace)SQL database | Message API calls it. History API calls it for reads.Postgres runs one process per connection, which is why poolers like PgBouncer sit in front of busy databases. | 6 vCPU · 75 connections |
| Message events (Kafka)Event stream | Message API publishes to it.Calls Real-time fan-out.Kafka keeps order only within a partition, so the partition key decides what stays in sequence. | 8 partitions · retention 600 s |
| Real-time fan-outWorker | Message events (Kafka) consumes from it.Calls Channel pub/sub (to WebSocket servers), Message search index, Mobile push.Queues deliver at least once, so a worker can see the same message twice. | 32 concurrent jobs |
| Channel pub/sub (to WebSocket servers)Pub/sub topic | Real-time fan-out calls it.Pub/sub delivers each message to every subscriber, so producers never know who listens. | 1250 slots |
| Message search indexSearch index | Real-time fan-out calls it.Search engines build an inverted index: each word points to the documents that contain it. | 32 slots |
| Mobile pushNotification service | Real-time fan-out calls it on 30% of requests.Email, SMS and push providers all throttle senders and can delay delivery. | 25 slots · 250,000 calls/min |
| History APIApp service | API gateway forwards to it for /read.Calls Messages (MySQL, sharded by workspace).Little's law: throughput ≈ concurrency ÷ latency. 200 slots at 50 ms serve about 4,000 req/s. | 1 replicas × 100 slots · timeout 1.0 s |
| Presence APIApp service | API gateway forwards to it for /presence.Calls Presence service.Little's law: throughput ≈ concurrency ÷ latency. 200 slots at 50 ms serve about 4,000 req/s. | 1 replicas × 100 slots · timeout 1.0 s |
| Presence servicePresence service | Presence API calls it.Presence is a heartbeat: each client pings every few seconds, and a status flips to away when the pings stop. | 625 slots |