Part 11 · Design It Yourself: Case Studies
A 5-Step Framework for Any System Design Problem
A blank whiteboard and “design Instagram” is terrifying without a plan. A five-step framework that works for any system design problem — requirements, estimation, API and data model, high-level design, deep dives — with a worked Pastebin example and the common mistakes to avoid.
On this page
The Problem
Someone says: "Design YouTube." Or "Design a chat app." Or, at work, "We need a notification system by next quarter."
It is easy to freeze. It is also easy to do the opposite: you start drawing Kafka clusters and sharded databases before anyone knows what the system should do. Both lead to bad designs:
- the first because nothing gets decided,
- the second because you are solving problems nobody has.
In the last 58 posts we learned the building blocks: load balancers, caches, databases, queues, replication, sharding, consistency, reliability patterns, observability and security. This part of the course puts them together. Before we design real systems, we need a process you can repeat. It is a framework that works for any design problem, in an interview or in a real design document. (Here, a "system" is a set of programs and machines that work together to do a job.)
The Core Idea
Think about how an architect designs a house:
- Listen: "How many people? What is your budget? Do you work from home?" (requirements)
- Measure: the size of the land, the number of rooms, and how much water and power you need (estimation)
- Define the connections: where the doors, pipes and wires go (the API, which is how parts talk to each other, and the data model, which is how data is organised)
- Sketch the floor plan: the main rooms and how they connect (the high-level design)
- Work out the hard parts: the staircase, the walls that hold up the house, safety in an earthquake (deep dives)
At the end, explain the choices: "We put the kitchen here because…, and we chose this over that because…". These are the trade-offs. A trade-off means you give up one good thing to get another.
A good system design follows the same shape. The framework keeps you organised. It makes sure you do not skip important questions. It also shows how you think, which matters more than any single "right answer".
How It Works
Key terms in plain words
- Functional requirement: something the system must do, such as "shorten a URL".
- Non-functional requirement: how well the system must do it, such as how fast, how reliable or how big.
- QPS: queries per second, the number of requests the system gets each second.
- Latency and p99: latency is how long one request takes. "p99 under 50 ms" means 99 out of 100 requests finish in less than 50 ms.
- Availability: the share of time the system works. "99.99%" allows only about 52 minutes of downtime a year.
- Back-of-the-envelope estimation: quick rough maths, like you would do on the back of an envelope, to learn how big the problem is.
- API (Application Programming Interface): the list of requests that other programs can send to your system, and the answers they get.
- Access pattern: how your data is read and written, for example "look up one row by its code".
- Bottleneck: the one part that is slowest, so it limits the whole system.
- SPOF (single point of failure): one part that, if it breaks, stops the whole system.
- Load balancer: a server that spreads incoming requests across several servers.
- Cache: a fast, small store that keeps copies of data that is read often, so you do not ask the slow database every time.
- CDN (content delivery network): a network of servers around the world that keeps copies of files close to users.
- Queue: a line of tasks waiting to be done. A program adds a task to the end, and a worker takes tasks from the front.
- Stateless: a server is stateless when it keeps no user data between requests, so any server can answer any request.
- Kafka: a popular system that stores a stream of messages so that many programs can read them. Microservices are many small programs that each do one job and talk over the network.
- Metadata: data about other data, for example the owner and expiry date of a paste.
The five steps at a glance
- 1Requirements~5 min — what it does and how well; what is out of scope
- 2Estimation~5 min — QPS, storage, bandwidth: how big is this?
- 3API & data model~5 min — the contract and the main access patterns
- 4High-level design~10 min — the fewest boxes and arrows that work end to end
- 5Deep dives~15 min — bottlenecks, failures, scaling, the interesting parts
- 6Wrap-up~5 min — trade-offs made, what you would do next
A rough time budget for a 45–60 minute interview:
| Step | Time |
|---|---|
| 1. Requirements | 5–8 min |
| 2. Estimation | 3–5 min |
| 3. API & data model | 5–8 min |
| 4. High-level design | 10–15 min |
| 5. Deep dives & scaling | 10–15 min |
| Wrap-up | 2–5 min |
In a real design document, the same steps become the sections of the document.
Step 1: Clarify requirements
Never start designing right away. Ask questions until the problem is clear (post 6).
Functional requirements: what does it do?
- Who are the users? (consumers, businesses, internal teams)
- What are the core use cases? Pick the 3–5 most important ones.
- What is out of scope (not part of this design)? Say it out loud: "I will skip payments and admin tools for now."
Non-functional requirements: how well must it do it?
- Scale: daily active users (people who use it each day), requests per second, data size, and growth.
- Latency: how fast must the key actions feel (p99 targets, post 8)?
- Availability: how bad is downtime (post 9)? Which parts are critical?
- Consistency: is slightly old (stale) data OK, or must every user see the exact latest data (posts 27–28)?
- Durability: may we ever lose saved data? (Durable data stays safe even after crashes.)
- Read/write ratio: is it read-heavy (feeds, product catalogues) or write-heavy (logs, chat)?
- Limits from geography, security, compliance (legal rules) and cost.
Write them down, and check them with the other person:
- •Shorten a long URL
- •Visiting the short URL redirects to the original
- •Optional: custom alias, expiry
- −Out of scope: accounts, analytics dashboards
- •100 M new URLs/month, ~100 : 1 reads to writes
- •Redirect p99 < 50 ms
- •Redirects 99.99% available
- •Links must never be lost
Step 2: Back-of-the-envelope estimation
Do quick maths to learn the size of the problem (post 10):
- Traffic: the average QPS and the peak QPS (the busiest moment), for reads and writes separately.
- Storage: per item × items per day × retention.
- Bandwidth: QPS × response size.
- Memory: how much hot data (data that is read often) to keep in a cache. The 80/20 rule says that about 20% of the data gets about 80% of the reads.
Always end with "so this means…":
- "Only ~40 writes per second, so one primary database handles writes easily."
- "~12,000 reads per second at peak, so we need caching and replicas."
- "About 6 TB over 10 years, which fits in a sharded or single large database."
Do not spend 15 minutes on arithmetic. Round the numbers a lot. The goal is the order of magnitude, which means "is it about 10, 1,000 or 1,000,000?".
Step 3: Define the API and data model
API. Write down the main endpoints (the URLs a client can call) or operations (posts 30–34). In the example, a 301 redirect is cached by browsers, and a 302 redirect is not:
POST /v1/urls { longUrl, customAlias?, expiresAt? } → 201 { shortUrl }GET /{code} → 301/302 redirect to longUrlThink about:
- idempotency for creates (it means that sending the same request twice has the same effect as sending it once, post 34),
- pagination for lists (returning a long list in small pages),
- authentication (checking who the caller is) and rate limits (a cap on how many requests one caller may send, posts 43 and 49),
- sync vs async: does the client need the result now (synchronous), or can the work run later as a background job (asynchronous, post 18)?
- whether REST, gRPC, GraphQL or WebSockets fits best. These are different styles for programs to talk to each other (posts 30–33).
Data model. List the core entities (the main kinds of things you store, like a user or a URL), their key fields, and the access patterns. In the example, PK means primary key, the field that identifies each row:
url_mappings: code (PK), long_url, created_at, expires_at, owner_idAccess pattern: lookup by code (very hot), insert (rare)Then choose the storage based on those patterns (posts 20 and 29): relational, key-value, wide-column, document, search or object storage.
Step 4: High-level design
Draw the main components and the flow of data that cover the core use cases from start to finish. Start simple, then improve it step by step:
- Client
- DNS / CDN
- Load balancer
- API servers
- Cache
- Database
- Queue → workers
Walk through each core use case on the diagram: "When a user creates a URL, the request goes here, then here… When someone visits a short URL, it goes here…"
Tips:
- Use the standard building blocks (post 11). Do not invent strange new components.
- Mark what is synchronous and what is asynchronous.
- Show where the data lives and which service owns it (the only one allowed to change it).
- Keep it readable: 6–12 boxes, not 40.
Step 5: Deep dives and scaling
Now go deeper on the hardest or most important parts. Pick 2–3 topics that matter most for this system, or follow what the interviewer asks:
Scaling:
- Where is the bottleneck when traffic grows 10 or 100 times?
- Cache hot data (posts 15–16). CDN for static content (post 14).
- Read replicas (extra copies of the database that only answer reads, post 24). Sharding (splitting data across several databases), with a clear shard key, the field that decides which database holds a row (posts 25–26).
- Queues to soak up sudden spikes of work (posts 18 and 35).
Reliability:
- SPOFs and redundancy (spare copies) across AZs, which are separate data centres (post 40).
- Timeouts, retries and circuit breakers (a circuit breaker stops calling a service that keeps failing, posts 41–42).
- Rate limiting and load shedding (load shedding means dropping some requests on purpose so the rest still work, posts 43–44).
- Backups and DR (disaster recovery: how you get running again after a big failure, post 45).
Data correctness:
- Consistency needs per feature (post 28).
- Transactions (a group of changes that all happen or none happen), idempotency, handling duplicates and keeping the right order (posts 21, 34 and 37).
Operability and security:
- Monitoring and SLOs: what would you alert on? An SLO (service level objective) is a reliability target, such as "99.9% of requests succeed" (posts 46–48).
- AuthN / AuthZ, sensitive data and abuse. AuthN (authentication) checks who you are. AuthZ (authorization) checks what you are allowed to do (posts 49–52).
- Deployments: how do you ship changes safely (post 58)?
Good deep dives compare options: "We could do A or B. A is simpler but fails when X. Given our requirement of Y, I would choose B."
Wrap-up: trade-offs and next steps
Finish by summing up:
- Key decisions and why (for example "hybrid fan-out, because of celebrity accounts". Fan-out means copying one post to many followers' feeds).
- Trade-offs accepted ("feeds may be a few seconds stale").
- Risks and bottlenecks you would watch.
- What you would do next with more time ("multi-region, better ranking, analytics").
A mini example: "Design Pastebin" in 5 steps
- Requirements: users paste text and get a link, and anyone with the link can read it. Pastes can optionally expire and are up to 1 MB. The system is read-heavy (about 10:1), and pastes must not be lost.
- Estimation: 1M new pastes a day ≈ 12 writes/s. 10M reads a day ≈ 120 reads/s (peak around 500/s). With an average paste of 10 KB, that is 10 GB a day ≈ 3.6 TB a year.
- API and data:
POST /pastesreturns{id}, andGET /pastes/{id}returns the content. Metadata (data about the paste, like owner and expiry) goes in a database. The content goes in object storage, a cheap service for storing big files (post 17). - High-level design:
- 1Client → load balancer → API serversstateless
- 2Metadata DBid, owner, expiry, storage key
- 3Object storagethe paste content itself — big and cheap
- 4CDN + cachepopular pastes and hot metadata
- 5Background workerdeletes expired pastes
- Deep dives: making IDs (random Base62 vs counters; Base62 uses the 62 characters a–z, A–Z and 0–9), caching popular pastes, cleaning up expired pastes, abuse (spam, malware, rate limits), and CDN caching rules.
Wrap-up: this is a simple, read-heavy design. Caching and a CDN (a network that serves copies of files from places near the user) give most of the scale, and object storage keeps the database small.
Common mistakes
- ❌ Jumping into details (Kafka partitions, database choice) before the requirements are clear.
- ❌ Designing for Google scale when the real need is 1,000 users.
- ❌ Silent thinking. Explain your reasoning as you go. The process matters.
- ❌ Buzzword architecture: adding trendy tools like microservices, Kafka, Kubernetes and GraphQL without saying why.
- ❌ Ignoring failure: acting as if every component always works.
- ❌ No trade-offs: showing one option as perfect. Every choice has a cost.
- ❌ Spending all the time on one part and never finishing the design from start to finish.
- ❌ Not checking back with the interviewer or stakeholders (people who care about the result), for example "Does this match what you had in mind?".
Communication tips
- Think out loud, and say your assumptions clearly ("I will assume 50M daily users").
- Check in at the end of each step.
- Start simple, then improve: "Version 1 is a single database. At 10 times the traffic we would add…"
- Use numbers to support your decisions.
- Admit uncertainty: "I am not sure about the exact limits of X, but I would check with a load test."
Trade-offs
- A structured framework makes sure you miss nothing important. But if you follow it too strictly, it can feel like a robot. Change how deep you go in each step to fit the problem.
- Time on requirements vs design: too little time on requirements leads to the wrong design, and too much leaves no time to design. Aim for clarity, not perfection.
- Breadth vs depth: cover the whole system first, then go deep on 2–3 areas. You cannot go deep everywhere in a short time.
In the Real World
Design docs at big tech companies. Companies like Google, Uber and many others write a design document or RFC (request for comments, a document that others review) before they build big systems. These usually include the background, goals and non-goals (things you will not do), the proposed design, other options that were considered, and topics that touch every part (security, privacy, monitoring, rollout plan). This is the same framework in written form.
Amazon's "working backwards". Amazon teams often start with a press release and FAQ (a PR/FAQ). It describes the product from the customer's point of view, before any design. It makes the team get clear on the functional requirements and the customer value first. This is exactly step 1.
Architecture Decision Records. Many teams write down important decisions as short ADRs (Architecture Decision Records, post 6). An ADR has the context, the decision, the other options and the results. It is the "wrap-up and trade-offs" step, saved for future engineers.
System design interviews. Most large tech companies have system design rounds for mid-level and senior engineers. Interviewers usually look for structured thinking, clear requirements, sensible estimates, a working end-to-end design, and thoughtful trade-offs, not architectures learned by heart.
Interview Questions
Q1What's the first thing you do in a system design interview?
Clarify the requirements. Pin down the core features and what is out of scope. Then write the non-functional requirements as numbers: scale, read/write ratio, latency, availability and consistency needs. Do this before you draw anything.
Q2Why do an estimate before designing?
The numbers decide the architecture. 40 writes a second fit on one primary database, but 400,000 do not. Estimation tells you whether you need caching, sharding, CDNs or queues, and where to spend your deep-dive time.
Q3How do you choose what to deep-dive on?
Follow the bottlenecks that your estimate shows, and the requirement that is hardest to meet. Examples are the busy read path, the table with many writes, or the flow where consistency is critical. Also look at the ways your design can fail. Ask the interviewer which area interests them.
Q4What are common system design interview mistakes?
Jumping into components before the requirements, building for a scale nobody asked for, naming technologies without explaining the trade-offs, ignoring how things fail, staying silent instead of thinking out loud, and never checking in with the interviewer.
Q5How should you wrap up?
Sum up the design and compare it with the requirements. State the key trade-offs you made and why. Point out the weak spots you know about. Say what you would add next with more time or more scale, such as monitoring, multi-region or analytics.
Key Takeaways
- Use a repeatable framework: requirements → estimation → API & data model → high-level design → deep dives, then a wrap-up of trade-offs.
- Clarify first: functional requirements, out-of-scope items, and measurable non-functional requirements (scale, latency, availability, consistency).
- Estimate to find the order of magnitude, and always end with "so this means…".
- Design end to end, simply first, walking each use case through the diagram. Then deep-dive into the 2–3 hardest parts: scaling, failures, correctness, security and operations.
- Explain trade-offs and assumptions out loud. There is no single right answer, only answers with good reasons.
Further Reading
- System Design Interview: An Insider's Guide by Alex Xu (chapter 3, "A Framework For System Design Interviews")
- The System Design Primer on GitHub (section "How to approach a system design interview question")
- The roadmap.sh System Design roadmap
- Malte Ubl's article "Design Docs at Google"
- Michael Nygard's article "Documenting Architecture Decisions"
Published by Jainik · Last updated · How these lessons are made
Keep learning
Part of the study guide
Related series