What a system design interview tests
You might be asked to design a URL shortener, a chat app, or a notification service. There is no single correct diagram. The goal is to show that your choices fit the requirements and that you understand what happens when traffic grows or a component fails.
For beginners, the most useful skill is explaining a complete request path before adding advanced infrastructure. You should be able to describe where data lives, how clients read and change it, and which guarantees the system provides. Expected depth varies by role and level.
- Scope: Can you turn a broad prompt into a small set of concrete requirements?
- Architecture: Can you connect clients, application servers, storage, and background work?
- Reasoning: Can you compare options instead of naming technologies?
- Correctness: Can you explain concurrent updates, retries, and partial failures?
- Communication: Can you state assumptions and respond to follow-up questions?
Start by clarifying requirements
Separate functional requirements, which describe user actions, from nonfunctional requirements, which describe constraints such as latency, availability, durability, and scale. Ask a few targeted questions, then propose assumptions if the interviewer leaves the decision to you.
For a URL shortener, a useful initial scope is creating a short link and redirecting visitors to its destination. Custom aliases, expiration, and analytics are separate features. Agree on which ones matter before designing them.
- Core actions: What must users be able to do?
- Workload: How many users, reads, writes, and concurrent connections should we plan for?
- Latency: Which operations need a quick response, and what target should we assume?
- Correctness: Can readers see stale data, or must changes take effect immediately?
- Durability: What must survive server or storage failures?
- Scope exclusions: Which features can wait until the core design is complete?
Use simple estimates to guide the design
Back-of-the-envelope estimates help identify the likely bottleneck. Start with requests per second, data growth, and payload size. Keep units visible and use rounded numbers. An estimate is useful only when it changes a design decision.
Suppose a URL shortener has one million daily users, each making ten redirects per day. That is ten million redirects per day, or about 116 requests per second on average. If you assume a five-times peak for this exercise, plan around 600 requests per second. The peak multiplier is an assumption, not a general rule.
- Average requests per second = requests per day ÷ 86,400.
- Raw storage growth = new records per day × average record size.
- At 100,000 new links per day and 500 bytes per record, raw growth is about 50 MB per day before indexes, replicas, and backups.
- Bandwidth ≈ requests per second × bytes transferred per request.
- Do not infer server counts from request rate alone. Capacity depends on the code, hardware, data access, and latency target.
Define the APIs and data model
APIs make the design concrete. Describe the main operations, their inputs and outputs, and important error cases. You do not need a complete specification, but you should explain what success means.
For a URL shortener, POST /links can accept a destination URL and return a short code. GET /{code} looks up the destination and returns an HTTP redirect. The data model might contain code, destination_url, owner_id, created_at, and expires_at, with a unique constraint on code.
Choose storage from access patterns and correctness needs. A relational database is a reasonable starting point for this example because it supports indexed lookups and uniqueness constraints. A key-value store can also fit, but you still need to explain unique-code creation, durability, and update behavior.
- Identify lookup keys and the indexes needed to support them.
- State which fields or relationships must be unique.
- Explain what happens when a code is missing, expired, or already taken.
- Discuss retry behavior for operations that create or change data.
- Use pagination for list APIs rather than returning an unbounded result.
Draw the simplest complete architecture
Begin with a client, an application service, and a database. Walk through a write and a read. Add a load balancer and multiple application instances when you need more serving capacity or resilience to an instance failure. Keep application instances stateless where practical so any healthy instance can handle a request.
For link creation, the service validates the URL, generates a code, and inserts the mapping. If the database rejects a code collision, the service generates another code and retries within a bounded limit. For a redirect, the service looks up the code, checks expiration, and returns the destination in a redirect response.
- Write path: client → application → database → response.
- Read path: client → application → indexed database lookup → redirect.
- Name the database as the source of truth for link mappings.
- Explain how the load balancer avoids unhealthy application instances.
- Choose redirect and cache behavior deliberately, especially if destinations can change.
Learn the building blocks and their trade-offs
System design basics are easier to learn as solutions to specific problems. Do not add a cache, queue, or shard just because it appears in a reference architecture. State the bottleneck first, then explain what the new component improves and what complexity it introduces.
- Load balancing spreads requests across servers. It helps application capacity and availability, but does not fix an overloaded shared database.
- Caching avoids repeated work or storage reads. It can reduce latency and database load, but introduces stale data, invalidation, and cache-miss bursts.
- Replication keeps copies of data. It can support failover and additional read capacity, but asynchronous replicas may lag behind writes.
- Message queues move work off the request path and absorb temporary bursts. They introduce processing delay, backlog management, and duplicate-delivery handling.
- Database indexes speed up selected queries. They consume storage and add work to writes.
- Sharding divides data across storage nodes. It can increase capacity, but makes routing, rebalancing, and cross-shard operations harder.
- Object storage holds large files such as photos and videos. Keep searchable metadata separately, and explain how uploads become visible safely.
Explain correctness and failure behavior
A design is incomplete until you explain what happens when a request succeeds in one component but fails in another. For example, a timeout does not prove that a database write failed. Retrying an operation can repeat its effects unless the system recognizes the same logical request.
Choose consistency requirements per operation. A delayed analytics count may be acceptable, while selling the same seat twice is not. Avoid describing the whole system as simply strongly consistent or eventually consistent without naming the data and operation involved.
For the URL shortener, analytics could run asynchronously, but redirects should not depend on the analytics pipeline being healthy. If destinations can change, a cache TTL bounds ordinary cache staleness; strict immediate changes require a stronger read or invalidation design.
- Use timeouts and bounded retries with backoff for transient failures; retry only when the operation is safe or deduplicated.
- Use idempotency keys or another deduplication mechanism when retries could repeat a side effect.
- Protect invariants with mechanisms such as unique constraints, transactions, or conditional updates.
- Explain what a database replica failure means for availability and acknowledged writes.
- Bound queues and concurrency so overload does not create unlimited work.
- Monitor request latency, error rate, storage health, and queue age; define recovery behavior, not just alerts.
Manage the interview as a conversation
For a 45-minute interview, one possible allocation is five minutes for requirements, five for estimates and APIs, ten for the baseline architecture, twenty for deeper discussion, and five for a recap. Adapt to the interviewer rather than treating this as a fixed script.
Say your reasoning out loud: “I will start with one logical database because the current workload does not justify sharding. I will add a cache if repeated reads become the bottleneck, and I will explain how destination updates reach it.” This communicates more than listing products.
- After scoping, confirm the two or three requirements that drive the design.
- Trace one request end to end before drawing more components.
- For each major choice, state the benefit, cost, and condition that would make you change it.
- Expect follow-ups such as: What gets stale? What happens on retry? Which key becomes hot? How does failover work?
- Finish by summarizing the request path, key guarantees, likely bottleneck, and remaining limitation.
Practice by adding one difficulty at a time
Start with problems whose core flow you can explain without advanced distributed algorithms. Build a complete baseline, then add a specific constraint such as a popular link, a duplicate notification, or an application instance failure. This teaches you to connect architecture changes to requirements.
After each attempt, check whether every component has a purpose and whether every important write has clear success and retry semantics. Avoid memorizing diagrams, choosing a database by brand, or claiming that caching and sharding solve every scaling problem.
- URL shortener: practice requirements, APIs, indexed lookups, code uniqueness, and caching.
- Notification system: practice queues, worker failures, retries, and duplicate delivery.
- Distributed rate limiter: practice algorithm choice, atomic updates, and failure policy.
- Photo storage service: practice metadata versus large objects, resumable uploads, and asynchronous processing.
- Repeat a problem with a changed constraint, such as editable links or a stricter freshness requirement.
- Record unresolved questions and study those concepts before attempting the design again.
Where it comes up
Questions to practice with this guide.
- Design a URL shortener like BitlyIts small core request path makes it a useful starting point for requirements, estimates, APIs, unique keys, and caching.
- Design a notification systemIt introduces asynchronous work, retries, and duplicate delivery after the learner understands a synchronous service.
- Design a distributed rate limiterIt makes algorithm trade-offs, atomic state changes, and availability decisions concrete in a focused design.
- Design Google PhotosIt teaches the separation of large objects from metadata and the failure handling needed for multi-step uploads.
Questions people ask
What should I learn before starting system design interviews?
Learn HTTP request and response behavior, database tables and indexes, basic transactions, caching, and background jobs. You should also understand timeouts, retries, and why a network failure can leave an operation's outcome unknown. You do not need to master consensus algorithms before practicing an end-to-end design.
How long does it take to learn system design basics?
It depends on your experience building and operating backend services and how much focused practice you do. Measure progress by whether you can scope a problem, trace reads and writes, justify storage choices, and explain failures without relying on a memorized diagram. Alternate concept study with full practice interviews so you can apply what you learn.
Do I need to know AWS services or specific databases?
Start with component roles and required guarantees rather than product names. Saying “a durable queue with at-least-once delivery” is more useful than naming a service without explaining duplicate handling. If you choose a specific product, be ready to explain the relevant behavior and limitations.