What system design is
From one sentence in a meeting to a design that survives failure, built one fix at a time.
What you will learn
- 01The question before the boxes
- 02Three stages, and a loop
- 03Requirements: what and how well
- 04Find the pain in the simple design
- 05Fix it one step at a time
- 06Everything is a tradeoff
The question before the boxes
System design is deciding which parts a product needs, what each part is responsible for, and how the parts talk to each other. Beginners start by drawing boxes: a cache here, a queue there. Boxes are answers, and you need the question first.
Our running example is a link shortener. A person pastes a long address and receives a short one. Later, anyone who opens the short address lands on the long one. We will start with the simplest thing that could work.
Swipe sideways to pan · drag a box to move it
Three stages, and a loop
Design has three stages. Requirements say what the system must do. High-level design says which parts exist and how they connect. Low-level design zooms into one part: its fields, keys and algorithms.
The stages are a loop, not a line. A storage choice in stage three can reveal a missing requirement from stage one, and that is normal. Going back is part of the process, not a failure of it.
Swipe sideways to pan · drag a box to move it
Requirements: what and how well
A functional requirement is a behavior: create a short link, redirect a short link, let a user pick a custom alias. A non-functional requirement is a quality: redirects are fast, the service stays up, keys cannot be guessed.
"Lots of traffic" cannot be designed for, but numbers can. Say we expect 500 million new links a month.
- A month is about 2.6 million seconds (30 x 24 x 3600).
- 500M divided by 2.6M is about 200 new links per second.
- If reads outnumber writes 100 to 1, that is about 20K redirects per second.
- Each record is about 500 bytes, so 5 years is 30 billion links, about 15 TB.
200 writes per second is easy for one database. 20K reads per second is where trouble starts. The numbers told us where to look.
Find the pain in the simple design
Our first design has one server and one database. Every request passes through that one machine. If it restarts, crashes, or is overloaded, every redirect fails.
A part whose failure takes the whole product down is a single point of failure. Naming the pain precisely is the most useful step in design, because the fix follows from it: stop having only one.
Swipe sideways to pan · drag a box to move it
Fix it one step at a time
Add a load balancer. Put it in front of two servers. It picks a server for each request and skips a dead one. Cost: the balancer itself can fail, so real systems run a pair.
Swipe sideways to pan · drag a box to move it
Cache the hot reads. A small set of links gets most of the hits, so keep them in memory. Caching the hottest 20 percent of a day's reads is about 170 GB. Cost: the cache can be stale after an edit, so each entry gets an expiry.
Swipe sideways to pan · drag a box to move it
Copy the database. A replica serves reads and survives the loss of the primary. Cost: a replica lags by a moment, so a brand new link may briefly miss there.
Swipe sideways to pan · drag a box to move it
Everything is a tradeoff
Every part you add buys something and costs something. Before adding one, finish two sentences: "This gives us..." and "This costs us...". If you cannot finish the second, you do not yet understand the part.
Also know when not to use it. A cache is wasted on a service with ten users a day. The simplest design that meets the numbers is the right design, and you can always come back to the loop when the numbers change.