Step 2: A high level design
Sketch the main components and connections, trace every use case through them, and justify each box.
What you will learn
- Sketch one box per kind of work and one arrow per way a request travels.
- Test the sketch by tracing every use case through it.
- Justify each component in one sentence tied to a use case or assumption.
Step 2: sketch and justify
The primer's second step is short: outline a high level design with all the important components. Sketch the main components and the connections between them, and justify your ideas.
"All the important components" means one box for each kind of work the use cases need, and one arrow for each way a request travels. It does not yet mean caches, replicas or extra servers: those answer bottlenecks, and you have not found any yet. The primer is explicit about this in step 4: do not jump straight from the initial design to the final one.
Follow each use case through the sketch
A good test of the sketch is to trace every in-scope use case through it. If a use case has no path, a component is missing; if a box is on no path, it may not be needed.
For Pastebin, the primer's design has a client, a web server acting as a reverse proxy, a Write API and a Read API, a SQL database, an object store and an analytics box:
- Create a paste: client → web server → Write API, which saves a row to the SQL database and the paste text to the object store, then returns the link.
- View a paste: client → web server → Read API, which looks the link up in the SQL database and, if it exists, fetches the text from the object store.
- Track analytics: monthly counts, not real time, so a batch job over the web server's logs, outside the request path.
- Delete expired pastes: a job that scans the database for expired rows, also outside the request path.
Justify each choice
Every box should have a reason you can say in one sentence, tied to a use case or an assumption:
- Separate Read and Write APIs, because reads outnumber writes 10 to 1 and the two can then be scaled independently.
- An object store for the text, so the database holds only small rows, and nobody has to manage file servers.
- A SQL database used as a large hash table from link to path. The primer notes a NoSQL key-value store would also work, and that the choice is a trade-off to discuss.
- Batch analytics, because the assumptions say analytics need not be real time.
If you cannot give a reason, the component is probably premature.
- Client: 1 × Clients & Users
- Web server (reverse proxy): 1 × Application Load Balancer
- Write API: 1 × App Compute Server
- Read API: 1 × App Compute Server
- SQL database: 1 × Primary Relational DB
- Object store: 1 × Object Storage (S3)
- Client sends requests to Web server (reverse proxy)
- Web server (reverse proxy) sends requests to Write API
- Web server (reverse proxy) sends requests to Read API
- Write API sends requests to SQL database
- Write API sends requests to Object store
- Read API sends requests to SQL database
- Read API sends requests to Object store
Key takeaways
- Leave caches, replicas and extra servers out of the first sketch: they answer bottlenecks you have not found yet.
- A use case with no path means a missing component; a box on no path may not be needed.
- If you cannot give a reason for a box, it is probably premature.
Sources
- System Design Primer: How to approach a system design interview question
- System Design Primer: Design Pastebin.com (or Bit.ly), steps 2 and 3
- System Design Primer: Design a system that scales to millions of users on AWS (separate read and write APIs)
Adapted from The System Design Primer by Donne Martin, licensed under CC BY 4.0. Changes were made.