System design: the 8 steps
A design round is graded on how you drive it. Say each step out loud before doing it, and keep an eye on the time.
| 1. Requirements | Functional: what must it do? Non functional: scale, latency, consistency, availability. Ask, don't assume. |
| 2. Numbers | Users, requests per second, read to write ratio, storage per year. Round hard; you only need the order of magnitude. |
| 3. API | Three to five endpoints or messages. Names and fields make the scope concrete. |
| 4. Data | Tables or keys, the primary key, the indexes your queries need. Where each piece of data lives. |
| 5. High level | Draw the boxes: client, load balancer, services, database, cache, queue. Walk one request through it. |
| 6. Deep dives | Pick the 2 or 3 hardest parts and go deep. Ask: "Which part would you like me to go into?" |
| 7. Failures | What breaks at 10x? What if the cache, the queue or a region dies? Retries, idempotency, backpressure. |
| 8. Trade-offs | Say what you chose, what you gave up, and what you'd change at the next order of magnitude. |
Numbers worth knowing
| 1 day | about 100k seconds, so 1M a day is about 12 per second |
| Memory read | about 100 ns |
| Redis or Memcached call, same zone | about 0.5 to 1 ms |
| Indexed Postgres or MySQL read | about 1 to 5 ms |
| Cross region round trip | about 50 to 150 ms |
| One Postgres primary | thousands to tens of thousands of simple writes a second |
| One Redis instance | about 100k simple operations a second |
| Availability | 99.9% is about 43 minutes down a month, 99.99% about 4 |
Phrases that help
- "Let me check the requirements before I draw anything."
- "I'll start simple and scale it when the numbers force me to."
- "The trade-off here is X for Y. Given what we said about Z, I'd choose X."
- "If this were 10x bigger, the first thing to break would be..."