TL;DR: Don't start by drawing boxes. Go through the same 4 steps every time:
- Requirements: features, plus CLASS (Consistency, Latency, Availability, Scalability, Security)
- Estimations: users, storage and queries per second (divide by 10⁵ for "per day → per second")
- Detailed design: APIs, data model and shard keys, then a 3-tier architecture you grow from
- Monitoring and alerting: metrics, alerts, backups
Below is each step with a worked example.
The most common mistake I see in system design interviews happens in the first minute. The candidate hears the question, picks up the marker and starts drawing boxes.
Ten minutes later there's a load balancer, three services and a cache on the board, and no clear idea of what is being built or for how many people.
The fix is not learning more technologies. It's following the same plan every time. I'll go through the four steps using a small Twitter-like app as the example.
Step 1: Requirements
Before drawing anything, agree on what you are building. There are two kinds of requirements.
Functional requirements are the features. In a real company, a product manager usually gives you these. For Twitter:
- Create an account and log in
- Post a tweet
- Follow other users
- Like and comment on tweets
- See a feed of tweets from people you follow
Keep the list short. Ask the interviewer which features matter most, and say out loud which ones you are leaving out.
Non-functional requirements are how well the system must work. This part is the engineer's job, not the product manager's. I remember them as CLASS:
- Consistency: does everyone need to see the same data at the same moment? For a feed, eventual consistency is fine. A tweet showing up a few seconds late hurts nobody.
- Latency: how fast must it respond? The feed should load quickly.
- Availability: how much downtime is acceptable? Five nines (99.999%) means only about 5 minutes of downtime in a whole year.
- Scalability: how much traffic must it handle, and how will that grow?
- Security: who can see and change what? This means proper authentication (you are who you say you are) and authorization (you are allowed to do this).
Don't just list these words. Say what each one means for this system. "Eventual consistency is fine for the feed, so I'll choose availability" is an answer. "It should be consistent and available" is not.
Step 2: Estimations
Estimations tell you where the hard part of the design is. You don't need exact numbers, just the right size.
Assumptions first. Write them down so the interviewer can follow your maths:
- 500M total users, 200M daily active users (DAU)
- 25% of DAU post one tweet a day, so 50M tweets a day
- Each user opens their feed 5 times a day
Capacity planning (storage). About how much data do we store?
- A tweet with its likes and comments is roughly 2 KB
- 50M tweets × 2 KB × 365 days ≈ 40 TB a year, before replication
QPS planning (queries per second). One trick makes this easy: a day has 86,400 seconds, so round it to 100,000 (10⁵).
- Reads: 200M users × 5 feeds a day = 1,000M a day, and 1,000M / 10⁵ = 10,000 reads per second
- Writes: 50M tweets a day, and 50M / 10⁵ = 500 tweets per second
Bandwidth is optional. Add it when the design moves large files, like videos or images.
Now use the numbers. Reads are far higher than writes, so this is a read-heavy system. That one fact drives the rest of the design: we will optimize for fast reads, even if writes get a little more expensive.
Step 3: Detailed design
This is the biggest step. I go through it in the same order every time.
APIs. List the main calls with their inputs and outputs:
postTweet(authToken, content) → tweetId
followUser(authToken, userId) → success / failure
likeTweet(authToken, tweetId) → success / failure
getFeed(authToken) → list of tweets
Data modelling. Define the tables and, most importantly, the shard key for each one. The shard key decides which machine a row lives on.
For the Tweets table, there are two choices:
- Shard by tweetId: one user's tweets are spread across every machine. To get one user's tweets, you have to ask all of them and combine the results (scatter-gather). That is slow.
- Shard by userId: all of one user's tweets are on one machine, so you go straight to it.
Shard by userId is better here. But say the trade-off: famous users with millions of followers make their machine very busy (a "hot" shard). You can handle that by adding more copies (replicas) of that shard.
Pointing out a problem with your own choice is a good sign, not a weak one.
High-level architecture. I always start from the basic 3-tier architecture:
The starting point for almost every design: web servers, app servers and DB servers, with a load balancer in front of each tier.
- Tier 1, web servers: the front door. They check who the user is (authentication) and call the right services to build a response (orchestration).
- Tier 2, app servers: the business logic, split into services such as users, orders and payments.
- Tier 3, DB servers: the data, usually one database per service, each with replicas.
A load balancer sits in front of each tier, so you can add machines to any tier on its own when traffic grows.
Then I grow it for the problem in front of me: a cache for the hot reads, queues for work that can happen later, and more services as the features need them. Then walk through one request from start to end. For example: "When I post a tweet, it goes into a queue. A worker finds my followers and adds the tweet to each of their feeds in the cache."
Then cover the building blocks, but only where they matter for this design:
- Sharding: what you split, and by which key
- Replication: how many copies, and what happens when one fails
- Caching: what you cache, and why (for example, each user's feed)
- Authentication and authorization: who can do what
- Anything specific to the problem: for a calendar it's reminders, for payments it's never charging twice
Step 4: Monitoring and alerting
Most candidates run out of time before this step. Save five minutes for it, because it shows you think about running the system, not just building it.
- Metrics to track: latency of each API, success and failure rates, and resource usage (CPU, memory, disk)
- Alerts: notify the on-call engineer when a metric crosses a set threshold
- Backups: for recovering lost data, and for offline reports and analytics
How I split a 45-minute interview
- Requirements: about 5 minutes
- Estimations: about 5 minutes
- Detailed design: about 25 to 30 minutes
- Monitoring and alerting: about 5 minutes
The interviewer will interrupt and take you deeper into one area. That's good: it's where the real signal is. The plan keeps you from getting lost when you come back.
Mistakes I see most often
- Drawing boxes before agreeing on requirements
- Doing the estimations and then never using them
- Choosing a shard key without saying why
- Naming technologies ("use Kafka") without saying what problem they solve
- Skipping monitoring completely
Wrapping up
You don't need to know every database to do well in a system design interview. You need a clear plan, and the habit of explaining why at each step.
Requirements, estimations, detailed design, monitoring. Practise them on a few problems and the order becomes automatic. Then you can spend your energy on the interesting parts.
Over to you: which step do you usually rush or skip in interviews? Tell me in the comments 👇
I write about system design and interview prep. If you're preparing for system design interviews, you can book a free 15-minute call:

Top comments (0)