A Framework for Approaching System Design Interviews
The framework covers how to ask the right clarifying questions, define the scope, make reasonable assumptions, identify constraints, evaluate trade-offs, and gradually move from high-level architecture to detailed technical decisions. The goal is not only to produce a strong design, but also to demonstrate a clear and organised problem-solving process.
- Interviews
- Requirements

A Framework to how to tackle this in interview and also in real life
What Are Interviewers Looking for in a System Design Interview?
A system design interview evaluates both your technical knowledge and your approach to solving complex, open-ended problems. Interviewers want to understand how well you know the main system design concepts, how deeply you can discuss each topic, and how you handle unclear or missing requirements.
Because these interviews often provide limited details, you are expected to ask the right clarifying questions, identify the main constraints, and make reasonable assumptions when needed. Your problem-solving process is just as important as the final design.
Some engineers jump directly into technical details without first taking a step back to understand the problem. A better approach is to begin with critical thinking: clarify the requirements, define the scope, identify possible trade-offs, and then move gradually into the technical design.
Ultimately, a system design interview is not only about what you know. It is also about how you think, organise the problem, communicate your decisions, and work with limited information.
What Interviewers Look for in a System Design Interview
What matters most is not only the final design, but also how you think, communicate, and make decisions.
- Handling ambiguity: You can work with open-ended questions such as, “Design a platform like YouTube,” and turn them into clear requirements.
- Structured thinking: You follow a logical approach instead of jumping directly into technical details.
- Asking useful questions: You clarify important details, such as the number of users, expected traffic, core features, and system constraints.
- Exploring different options: You present alternatives and explain their advantages and disadvantages. For example, choosing between SQL and NoSQL databases.
- Understanding trade-offs: You explain why one option is more suitable than another. For example, choosing availability over strong consistency for a social media feed.
- Making reasonable assumptions: When information is missing, you state clear assumptions and continue with the design.
- Technical knowledge and experience: You understand fundamental concepts such as load balancers, caching, databases, queues, and replication, and can relate them to your practical experience.
- Leadership and decision-making: You take ownership of the design, make well-reasoned decisions, manage trade-offs, and adapt your approach when new information is introduced.

System Design Framework
1. Start by Clarifying the Problem
System design problems are often presented in only one or two sentences. Before proposing an architecture, clarify what the system must do, how well it must perform, and what is outside the scope of the discussion.
The goal of this step is to:
- Define the functional requirements.
- Identify the non-functional requirements, also called quality attributes.
- Clarify what is out of scope.
- Confirm important assumptions.
- Identify constraints that may affect the design.
- Agree on the most important use cases before discussing architecture.
Ask focused questions rather than trying to discover every possible requirement. Prioritize questions that could materially change the design.
When appropriate, propose a reasonable default based on your experience instead of waiting for the interviewer to provide every answer.
For example:
“Should shortened URLs expire? If this is not a core requirement, I will assume they do not expire, but I can design the system so that expiration can be added later.”
This demonstrates experience, keeps the discussion moving, and makes your assumptions explicit.
As you ask questions, identify whether each question relates to:
- Functional requirements
- Non-functional requirements
- Scope
- Assumptions
- Constraints
Functional Requirements vs. Non-Functional Requirements
Understanding the difference between functional and non-functional requirements is essential because they influence different parts of the architecture and testing strategy.
Functional Requirements
Functional requirements describe what the system must do. They are usually expressed as user actions, system behaviours, or business use cases.
A useful way to identify functional requirements is to ask:
- Who will use the system?
- What actions can each type of user perform?
- What inputs does the system accept?
- What outputs or responses should it produce?
- What business rules must be enforced?
- Which external systems must it communicate with?
For example, the main functional requirements of a URL-shortening service could be:
- A user submits a long URL and receives a shortened URL.
- A user visits the shortened URL and is redirected to the original URL.
- A user may optionally create a custom alias.
- A shortened URL may expire after a configured period.
- The system may record usage statistics for each shortened URL.
Other common functional areas include:
- User registration and account management
- Authentication and authorization
- Search and filtering
- Notifications
- Reporting and analytics
- Administrative capabilities
- Integration with external systems
- Data import and export
- Business rules and validation
Authentication and authorization are functional capabilities. However, the strength of the security controls, encryption requirements, and resistance to attacks are usually treated as non-functional security requirements.
Compliance may affect functional behaviour, non-functional requirements, and constraints. For example, a requirement to allow users to delete their data is functional, while a required retention period may be a constraint.
Focus primarily on the core use cases stated in, or directly implied by, the problem. Discuss secondary capabilities such as reporting, integrations, and administration only when they are relevant or explicitly requested.
Non-Functional Requirements
Non-functional requirements describe how well the system must operate. They are often called quality attributes.
Common non-functional requirements include:
- Scalability: How much traffic, data, or growth must the system support?
- Availability: How often must the service be accessible?
- Reliability: How consistently must the system behave correctly?
- Latency: How quickly must the system respond?
- Throughput: How many requests or operations must it process per second?
- Durability: How likely is stored data to survive failures?
- Consistency: How quickly must all users or replicas observe the same data?
- Security: How should data and system access be protected?
- Privacy: How should personal or sensitive data be handled?
- Recoverability: How quickly must the system recover from a failure?
- Observability: How will the system be monitored, traced, and debugged?
- Maintainability: How easy should the system be to modify and operate?
- Cost efficiency: What infrastructure or operational cost limits must be considered?
- Accessibility: Which accessibility standards must the product meet?
- Compliance: Which legal, regulatory, or industry obligations apply?
Whenever possible, make non-functional requirements measurable.
Instead of saying:
“The system should be fast.”
Prefer:
“The redirect endpoint should have a p95 latency below 100 milliseconds.”
Instead of saying:
“The system should be highly available.”
Prefer:
“The redirect service should provide 99.99% monthly availability.”
For a URL-shortening service, useful non-functional questions might include:
- How many shortened URLs are created each day?
- How many redirect requests occur per second?
- What is the expected read-to-write ratio?
- What redirect latency is acceptable?
- What availability target is required?
- Can analytics be eventually consistent?
- Can the system temporarily serve stale data?
- How long must shortened URLs remain available?
- How much data loss, if any, is acceptable?
- Does the service need to operate across multiple regions?
Remember
Connect Requirements to Testing
Requirements should guide both the architecture and the testing strategy.
This is more for you to understand, you don’t really want to bring it in the interviews unless explicitly asked.
Testing Functional Requirements
Functional requirements are commonly validated through:
- Unit testing
- API testing
- UI testing
- Integration testing
- End-to-end testing
- Regression testing
- Smoke testing
- Contract testing
- User acceptance testing
For example, a functional test for a URL-shortening service could verify that:
- A valid long URL is submitted.
- The API returns a shortened URL.
- Visiting the shortened URL redirects the user to the original URL.
Testing Non-Functional Requirements
Non-functional requirements are commonly validated through:
- Performance testing
- Load testing
- Stress testing
- Spike testing
- Scalability testing
- Soak or endurance testing
- Failover and recovery testing
- Resilience and chaos testing
- Security and penetration testing
- Disaster-recovery exercises
- Accessibility testing
- Reliability and availability monitoring
For example:
- A load test can verify that the redirect service supports the expected requests per second.
- A stress test can identify the point at which the system begins to fail.
- A failover test can verify that traffic moves to a healthy region after an outage.
- A penetration test can identify weaknesses in authentication, authorization, and input validation.
- A recovery test can confirm that the system meets its recovery time and recovery point objectives.
Not every quality attribute is proven by a single test. Requirements such as availability and reliability are also validated through production monitoring, service-level indicators, alerts, incident reviews, and long-running operational data.
Define What Is Out of Scope
Especially at senior levels, it is important to control the scope of the discussion.
Explicitly state which capabilities will not be covered unless they materially affect the design.
For example:
“I will focus on URL creation and redirection. I will treat billing, advanced analytics, custom domains, and abuse-detection workflows as out of scope unless you would like to explore one of them.”
Declaring something out of scope does not mean it is unimportant. It means you are deliberately prioritizing the areas that matter most for the current discussion.
A useful scope statement should identify:
- The core use cases being designed
- Secondary features that will not be explored
- External systems that will be treated as existing dependencies
- Operational concerns that will be discussed only at a high level
Track Assumptions and Constraints
Keep a small list of assumptions and constraints throughout the discussion. Revisit it whenever the interviewer introduces new information.
Constraints
A constraint is something the design must work within.
Examples include:
- The system must use an existing SQL Server database.
- The solution must run in a specific cloud provider.
- Data must remain within a particular country or region.
- Existing clients cannot be changed.
- The system must support an existing API contract.
- The project has a fixed cost or delivery deadline.
- A particular messaging or identity platform must be reused.
A constraint may prevent you from choosing what would otherwise be the ideal technical solution.
For example:
“A key-value database may be a natural fit for URL lookups. However, because the organization requires us to use the existing SQL Server platform, I will design around that constraint and explain the resulting trade-offs.”
Interviewers may introduce constraints to evaluate how well you adapt instead of simply choosing your preferred technology.
Assumptions
An assumption is something you are temporarily treating as true because it has not yet been confirmed.
Examples include:
- Most traffic will be reads rather than writes.
- Shortened URLs will not expire by default.
- Analytics do not need to be strongly consistent.
- Users do not need to choose custom aliases.
- Redirects must continue working even when the analytics pipeline is unavailable.
- The initial launch will operate in one geographic region.
- Malicious URL detection is handled by an external service.
State important assumptions explicitly:
“I will assume the workload is read-heavy, with approximately 100 redirect requests for every URL-creation request. I will validate that assumption before estimating capacity.”
Assumptions should be confirmed, challenged, or revised as the discussion progresses.
A Practical Questioning Framework
A structured questioning sequence can help you gather enough information without turning the conversation into an interrogation.
1. Clarify the Users
- Who uses the system?
- Are there different user roles?
- Are users internal, external, or both?
- Are anonymous users supported?
2. Clarify the Core Use Cases
- What are the primary user journeys?
- Which operations are essential?
- Which capabilities are optional?
- What happens when an operation fails?
3. Clarify the Data
- What data is stored?
- How is the data accessed?
- How long must it be retained?
- Is any of it sensitive?
- Are there data residency or deletion requirements?
4. Clarify the Scale
- How many users are expected?
- What is the expected request rate?
- What is the read-to-write ratio?
- How much data will be created?
- Are traffic patterns stable or bursty?
5. Clarify the Quality Attributes
- What latency is acceptable?
- What availability is required?
- How much data loss is acceptable?
- Is strong consistency required?
- Does the system need multi-region support?
6. Clarify Scope and Constraints
- Which capabilities are out of scope?
- Must existing systems or technologies be reused?
- Are there regulatory, budget, or timeline constraints?
- Are there existing APIs or clients that cannot change?
After gathering enough information, summarize your understanding before moving to the design:
“To confirm, we are designing a read-heavy URL-shortening service. The core use cases are creating a short URL and redirecting users to the original URL. Redirect latency and availability are the main priorities. Basic analytics are required, but they may be eventually consistent. Custom domains, billing, and advanced abuse prevention are out of scope.”
This creates alignment and gives the interviewer an opportunity to correct any misunderstanding.
How Expectations Change by Engineering Level
| Level | Typical Expectations |
|---|---|
| Junior Engineer | Understands basic components and can design a simple system with guidance. The discussion usually focuses on fundamentals, clear reasoning, and basic request and data flows. |
| Mid-Level Engineer | Can independently design a standard system, explain the major components, estimate basic scale, and discuss common trade-offs such as SQL versus NoSQL or caching versus direct database access. |
| Senior Engineer | Handles ambiguity well, defines and prioritizes requirements, identifies failure scenarios, considers scalability and reliability, and makes clear technical decisions with limited guidance. Connects requirements to testing, monitoring, and operational behaviour. |
| Staff or Principal Engineer | Looks beyond a single service. Considers multi-region architecture, cost, security, migrations, organizational ownership, cross-team dependencies, operational complexity, and the long-term evolution of the system. Clearly distinguishes immediate needs from future capabilities and avoids unnecessary complexity. |
The more senior the role, the less the discussion is about naming technologies and the more it is about:
- Framing an ambiguous problem
- Identifying the most important trade-offs
- Making and communicating defensible decisions
- Designing for failure and recovery
- Managing scope and complexity
- Connecting technical decisions to business and operational outcomes
2. Back of the envelope estimation
Back-of-the-Envelope Estimation
After clarifying the scope and identifying the functional and non-functional requirements, you may perform a few high-level calculations.
The goal is not to produce perfectly accurate numbers. It is to demonstrate that you can reason about scale and use estimates to guide architectural decisions. You can perform an initial calculation at this stage, then refine or validate the numbers later when discussing specific non-functional requirement and trade-offs.
For example, for a URL-shortening service:
Writes:
-
Write volume: Assume 100 million URLs are created per day.
-
Average write throughput:
100,000,000 ÷ (24 x 60 x 60) ≈ 1,160 writes per second -
Use powers of ten for quick estimation: A common technique is to convert large numbers into powers of ten. For example,
100,000,000becomes10^8, and the number of seconds in a day,24 × 60 × 60 = 86,400, can be approximated as10^5. Therefore:10^8 ÷ 10^5 = 10^3 ≈ 1,000 writes per secondThis provides a quick order-of-magnitude estimate. The more precise result is approximately
1,160 writes per second, but1,000 writes per secondis usually sufficient for an initial system design calculation.
Read : Write Ratio:
- Read-to-write ratio: Assume redirects outnumber URL creations by 10:1.
- Average read throughput:
1,160 × 10 ≈ 11,600 reads per second
Storage:
-
Number of records: Assume the service retains URLs for 10 years.
100 million × 365 × 10 = 365 billion records -
Assume the average original URL requires 100 bytes.
365 billion × (100 bytes + extra 100 bytes for the metadata) ≈ 73 TB
It is important to explain your assumptions and calculations to the interviewer so that you remain aligned. The estimates do not need to be exact; they should be reasonable enough to identify the expected scale and guide decisions such as caching, partitioning, and database selection for later.
Entities and Relationships
At this stage, identify the main entities required to support the functional requirements. Focus only on entities that are relevant to the agreed scope.
You may also describe the important relationships between those entities.
For example, in a URL-shortening system, the main entities could be:
- User
- URL Mapping
- Click Event, if basic analytics are required
Possible relationships include:
- A user can create multiple URL mappings.
- A URL mapping connects one short code to one original URL.
- A URL mapping can have multiple click events.
You do not need to define the complete database schema at this stage. The goal is to establish the main domain objects and how they relate to one another.
APIs or Interfaces
APIs and Interfaces
At this stage, define how users, clients, services, and external systems interact with the system. This may include APIs, events, messages, commands, or other input and output interfaces.
Not every API needs to be RESTful. The communication style depends on the problem, its complexity, and the type of interaction required. A system may use one or more of the following:
- REST for common client-to-server request and response operations
- gRPC for efficient communication between internal services
- WebSockets for real-time, bidirectional communication
- GraphQL for flexible client-side data retrieval
- Message queues or events for asynchronous communication
For simple problems, you may define the main APIs at this stage. For example, a URL-shortening service could expose:
- Create a short URL:
POST /urls - Redirect to the original URL:
GET /{shortCode} - Retrieve URL details:
GET /urls/{shortCode}
For more complex systems that require multiple communication methods, the detailed APIs may not yet be clear. In that case, focus first on the system’s high-level interfaces:
- What input does the system receive?
- What output does it produce?
- Who or what communicates with the system?
- Is the interaction synchronous, asynchronous, or real-time?
For example, the high-level interface of a web crawler could be:
The crawler as interface, receives one or more seed URLs as
inputand produces the extracted text and metadata from the discovered web pages asoutput. Crawler: Input: URLs, Output: Text
This is enough to establish the system boundaries during the initial discussion. The detailed API contracts and communication protocols can be defined after completing the high-level design, when the main components and their interactions are clearer.
Data flows (Optional - Mainly for systems that behave like pipelines)
Data flow is useful, especially for systems that behave like pipelines, such as web crawlers, data-processing platforms, streaming systems, or recommendation systems. The interface explains what enters and leaves the system, while the data flow explains how information moves through the major components. At this stage, keep it high-level; the detailed sequence can be refined during the high-level design.
For example, the high-level data flow of a web crawler could be:
- Retrieve the next URL from the URL frontier.
- Fetch the page’s HTML content.
- Parse the HTML to extract the text, metadata, and hyperlinks.
- Store the extracted content and metadata in the database.
- Normalize, validate, and deduplicate the discovered URLs.
- Add new, uncrawled URLs to the URL frontier.
- Repeat the process until the frontier is empty or a defined crawling limit is reached.
The flow can be summarized as:
URL Frontier → Fetch HTML → Parse Content and Links → Store Content → Filter and Deduplicate URLs → URL Frontier
Remember
You may give high level explanation here on which API type used, and for which reason and you may get some follow up questions from the interviewer. Below are some of questions to clarify the main concepts
Why did you choose REST here?
I chose REST because the interaction is request-response based, the resources are easy to model, and broad client compatibility is important. It is simple to implement, debug, cache, and expose externally. I would reconsider it if we needed real-time communication, very low latency, or high-volume service-to-service calls.
Follow-up: Are RESTful APIs stateless?
Yes. In a RESTful API, each request should contain all the information needed to process it. The server should not depend on session data stored from a previous request. For example, the client sends its authentication token with every request.
Statelessness does not mean that the system stores no data. The application can still store users, orders, URLs, and other persistent data in a database. It only means that the server does not rely on client session state being stored locally between requests.
Follow-up: Why is statelessness useful?
Statelessness makes the service easier to scale because any server instance can handle any request. This simplifies load balancing, failover, and horizontal scaling.
The main trade-off is that each request may need to include additional context, such as authentication credentials. If session state is required, it should usually be stored in a shared system such as Redis rather than in the memory of a single server instance.
Why did you choose gRPC over REST here?
I chose gRPC because this is internal service-to-service communication where low latency, efficient serialization, and strongly typed contracts are important. It also supports streaming and automatic client generation. The trade-off is that it is less convenient for browsers and public APIs than REST.
Why did you choose WebSockets here?
I chose WebSockets because the system requires low-latency, bidirectional communication over a persistent connection. This allows both the client and server to send updates without creating a new HTTP request each time. It is suitable for use cases such as chat, live collaboration, gaming, and real-time tracking.
Follow-up: What are the main trade-offs of WebSockets?
WebSockets introduce additional complexity around maintaining long-lived connections, reconnecting disconnected clients, load balancing, connection state, heartbeats, and scaling message delivery across multiple servers.
Why did you choose a webhook here?
I chose a webhook because another system needs to be notified when a specific event occurs, but it does not need a persistent connection. The source system sends an HTTP request to a callback URL provided by the receiving system.
For example, a payment provider may send a webhook when a payment succeeds or fails.
Follow-up: What should you consider when designing webhooks?
Webhook delivery should normally support retries, authentication or signature verification, idempotency, timeout handling, and monitoring. The receiver should acknowledge the request quickly and process longer-running work asynchronously.
Because webhooks may be delivered more than once, the receiving system should use an event ID or idempotency key to prevent duplicate processing.
What is the difference between WebSockets and webhooks?
| WebSockets | Webhooks |
|---|---|
| Maintain a persistent connection | Use a separate HTTP request for each event |
| Support bidirectional communication | Primarily provide one-way event notifications |
| Commonly connect a server to an active client | Commonly connect one backend system to another |
| Suitable for frequent, low-latency updates | Suitable for occasional event-driven notifications |
| Require connection and reconnection management | Require retry, authentication, and duplicate-handling logic |
A concise interview answer could be:
WebSockets are suitable when both sides need frequent, low-latency communication over a persistent connection. Webhooks are suitable when one system needs to notify another system that an event has occurred using a standard HTTP callback. For example, I would use WebSockets for live chat updates and a webhook for notifying a merchant that a payment has completed.
Why did you choose GraphQL over REST here?
I chose GraphQL because different clients need different combinations of related data, and we want to avoid multiple requests or returning unnecessary fields. It gives clients flexibility through a single schema. The trade-off is more complexity around caching, authorization, query cost, and preventing expensive requests.
Why did you choose a queue here?
I chose a queue because the work does not need to complete within the original request. It decouples the producer from the consumer, absorbs traffic spikes, supports retries, and allows consumers to scale independently. The trade-off is eventual consistency and additional complexity around duplicate messages, ordering, failures, and monitoring.
General Interview Approach
Do not choose a communication method only because it is common. Tie the decision to a requirement:
“I chose this approach because it supports the required latency, traffic pattern, consistency model, and client interaction. The main trade-off is …, which is acceptable here because …”
High-Level Design
Use the information gathered during:
- The requirements stage, including the main use cases
- APIs or interfaces
- Any identified data flow
To create the high-level design.
Focus on the system’s major components and how they communicate. Avoid going into implementation details at this stage; those can be explored later during the deep-dive discussion.
For example, the high-level design may show separate components for read and write operations which is transferring the functional requirements without immediately describing the solution as CQRS which is usually used in the deep dive stage to explain how we deal with specific non-functional requirement like such as high read throughput, independent scaling, or different consistency needs.
Remember
- Usually with High level design, you start by the functional requirements, you draw very high level boxes with very high level names, no need to include all the entities you wrote in the 1st stage.
- Then 2nd stage you traverse to the entities, interfaces, data flows and make sure they are included,
- Then 3rd stage is the deep dive when you take each non-functional requirement and do deep dive to make sure it’s fulfilled.
Final Notes
-
Express functional requirements as user capabilities: A useful format is:
“As a user, I can…”For example:
- As a user, I can create a short URL from a long URL.
- As a user, I can open a short URL and be redirected to the original URL.
-
Select only the non-functional requirements that are relevant to the problem: Make them measurable whenever possible, and use estimates to support them.
For example:
- The system may serve 100 million users per day and process 1 billion URL redirects per month, so it must be scalable enough to handle the expected traffic.
- The redirect endpoint should have a p95 latency of no more than 200 milliseconds.
- If redirects are business-critical and downtime must be minimal, the system may require a target such as 99.99% availability.
High traffic supports the need for scalability and sufficient throughput. High availability should be based on how much downtime the business can tolerate, not only on the number of users.
-
Reuse numbers during back-of-the-envelope estimation: You may already have captured traffic, storage, or latency figures while discussing the requirements. There is no need to introduce completely new numbers. Briefly restate those assumptions and organize them as part of the back-of-the-envelope estimation.
Up next
System Design
URL Shortening
A system design problem where we explain how to design a URL-shortening service similar to Bitly, along with a clear framework for approaching and solving system design questions in interviews.
- System Design
- URL Shortening
- Interviews
System Design
Introduction to Clean Modern Architecture
Explore architecture through Point and workshop-session examples, SOLID, component cohesion, domain-centric patterns, and the future of code with generative AI.
- architecture
- clean-architecture
- object-oriented
Comments
No comments yet
Log in to join the conversation. Members comment with a username; your email is never shown. Read the community rules.