System Design Process
A structured process for moving from a problem statement to a defensible system design. Applies equally to software design interviews, architecture reviews, and agent-assisted design tasks. The process is iterative — revisit earlier steps as constraints sharpen.Step 1: Requirements Clarification
Before drawing any boxes, define what the system must do and what constraints it operates under. Ambiguous requirements produce the wrong architecture.Functional requirements (what the system does)
- Who uses this system and how? (end users, internal services, third-party integrations)
- What are the core use cases? List the 3–5 most critical user flows.
- What are the inputs and outputs?
- What operations must be supported? (read, write, delete, search, stream, etc.)
Non-functional requirements (how well the system does it)
Common mistakes at this step
- Jumping to solutions before requirements are clear
- Treating all requirements as equally important — force-rank them
- Ignoring failure cases: what happens when a dependency is down?
- Not asking about the read/write ratio — it drives almost every subsequent decision
Step 2: Capacity Estimation
Back-of-the-envelope calculations to bound the design space. Do not skip this — it determines whether you need sharding, caching, a CDN, or none of the above.QPS estimation
Storage estimation
Bandwidth estimation
Latency reference numbers (memorize these)
These numbers constrain which designs are viable. If your design requires 5 database reads per request and each read is 1 ms, you cannot achieve a 2 ms p99.
Step 3: High-Level Component Decomposition
Sketch the major components and their interactions before designing any one of them in detail.Standard component checklist
- Client layer: web, mobile, third-party API consumers
- Load balancer / reverse proxy: traffic distribution, SSL termination
- Application servers: stateless services handling business logic
- Caching layer: Redis/Memcached for hot reads
- Primary datastore(s): SQL or NoSQL per access pattern
- Message queue: async work, decoupling producers from consumers
- CDN: static assets, geographically distributed content
- Background workers: jobs, batch processing, retries
Decomposition heuristics
- One box per bounded responsibility — if a box does two things, split it
- Draw the data flow, not just the components: where does data enter, transform, and exit?
- Identify the single point of failure in your first sketch — every design has one; acknowledge it
- Ask: which component fails most often? Design for that failure first.
Step 4: Data Flow Mapping
Trace the path of a request from client to storage and back. For each hop, identify:- What protocol is used? (HTTP/REST, gRPC, message queue, WebSocket)
- Is this synchronous or asynchronous?
- What are the consistency requirements at this boundary?
- What happens if this hop fails?
API contract design first
Define the API before implementing the internals. This forces clarity on:- What data does the client actually need?
- What operations are exposed?
- What are the latency SLAs for each endpoint?
Step 5: Tradeoff Articulation
Every design decision involves competing constraints. A good design articulates these explicitly rather than pretending they don’t exist.Common tradeoff axes
How to reason about competing constraints
- State the constraint: “we need < 100ms p99 latency”
- Identify what violates it: “5 synchronous DB reads per request at 20ms each = 100ms before any compute”
- Name the tradeoff: “we can cache the top 80% of hot reads in Redis at the cost of up to 1s staleness”
- Assert acceptability: “1s staleness is acceptable because [business reason]”
Step 6: Scale the Design
Only after a working baseline exists, identify bottlenecks and address them with targeted techniques. Scaling interventions in rough order of complexity:- Add caching (cheapest; reduces DB load significantly)
- Add read replicas (read-heavy workloads)
- Vertical scale (buy time; not a long-term solution)
- Horizontal scale / stateless services (application layer)
- Database sharding (when a single DB node is the bottleneck)
- CDN (static assets, geographically distributed reads)
- Async offload via message queue (decouple slow operations)
Common Interview / Design Mistakes
Cross-references
- Architectural Patterns — monolith, microservices, CQRS — structural choices made after requirements are clear
- Distributed Systems — CAP, eventual consistency, saga — constraints that shape distributed designs
- Scalability and Reliability — caching, sharding, load balancing, observability — scaling mechanics
- API Design Patterns — REST, gRPC, API contract conventions