How to Ace the System Design Round
How to Ace the System Design Round
The system design interview is the most open-ended round in software engineering hiring. There is no single correct answer — you are evaluated on how you structure your thinking, communicate trade-offs, and demonstrate awareness of real-world constraints. This guide covers the framework, key concepts, and worked examples to help you prepare.
What Interviewers Are Actually Evaluating
System design interviews test whether you can:
- Decompose a vague problem into concrete requirements
- Estimate scale to determine what kind of infrastructure is needed
- Design components that address those requirements
- Communicate trade-offs clearly and defend your choices
- Adapt when the interviewer introduces new constraints
They are NOT looking for a perfect answer from memory — they want to see your reasoning process.
The Structured Framework
Step 1: Clarify Requirements (5–10 minutes)
Never jump straight into design. Ask about:
Functional requirements — what the system must do:
- "Should users be able to edit posts after publishing?"
- "Do we need real-time updates or is eventual consistency acceptable?"
- "Should shortened URLs be permanent or expire?"
Non-functional requirements — quality attributes:
- Scale: "How many users? What's the daily active user count?"
- Latency: "Is this read-heavy or write-heavy? What latency is acceptable?"
- Availability: "What's the SLA — 99.9% or 99.99%?"
- Consistency: "Does it matter if two users see slightly different data for a short window?"
Step 2: Back-of-the-Envelope Estimation
Estimate traffic and storage before designing. This determines whether you need one database or ten, whether you need a CDN, how much caching to plan for.
Key numbers to memorize:
| Unit | Value |
|---|---|
| 1 million requests/day | ~12 requests/second |
| 100 million DAU | ~1,000 requests/second (1 rps per 100 DAU rule of thumb) |
| Average tweet size | ~300 bytes |
| 1TB | 1,000 GB |
| Disk read speed (SSD) | ~500 MB/s |
| Memory read | ~50 GB/s (much faster than disk) |
| Network (datacenter) | ~1–10 Gbps |
Example: Twitter-scale URL shortener
- 100M URLs created/day → ~1,200 writes/second
- 10:1 read-to-write ratio → ~12,000 reads/second
- Average URL length ~100 chars → 10GB/day storage for URLs
- Over 5 years: ~18TB of URL storage
This tells you: you need a distributed, highly available read path; writes are manageable on a single primary with replicas.
Step 3: High-Level Design
Draw the major components and their connections. A typical web application might include:
Client → Load Balancer → App Servers → Cache (Redis)
→ Primary DB → Read Replicas
→ Object Storage (S3)
→ Message Queue (Kafka)
Identify: Is this read-heavy or write-heavy? Will you need a CDN? How do components communicate (sync vs. async)?
Step 4: Deep Dive Key Components
Pick 2–3 components and go into detail on the ones most relevant to the problem. Common deep dives:
- Database schema design — what tables/documents, what indexes
- API design — REST endpoints, request/response shapes
- Caching strategy — what to cache, cache eviction policy (LRU, LFU), cache invalidation
- Data partitioning (sharding) — how to split data, what's the shard key, how to handle hotspots
Step 5: Address Scale and Failure
Every system design should end with: "how does this hold up at 10x load?" and "what happens when a component fails?"
- Horizontal scaling: Which components can be scaled by adding more instances? (App servers: yes; relational databases: harder)
- Single points of failure: Is there any component where failure brings down the whole system? Add redundancy.
- Cache failure: What happens if Redis goes down? Do requests fall through to the database gracefully?
Core Concepts You Must Know
The CAP Theorem
In a distributed system, you can guarantee at most two of three properties simultaneously:
| Property | Meaning |
|---|---|
| Consistency | Every read receives the most recent write (or an error) |
| Availability | Every request receives a response (not necessarily the latest data) |
| Partition tolerance | The system continues operating even if some nodes can't communicate |
Since network partitions are inevitable in real distributed systems, you must choose between C and A during a partition:
- CP systems (e.g., HBase, Zookeeper): Return an error or timeout if partition occurs — correct data or nothing
- AP systems (e.g., Cassandra, DynamoDB): Return possibly stale data — always available but not always consistent
Interview implication: Know when to choose AP vs. CP. A shopping cart (high availability matters, slight staleness is OK) → AP. A banking transaction (must be consistent) → CP.
Caching Strategies
| Strategy | Description | Use case |
|---|---|---|
| Cache-aside (lazy loading) | App checks cache first; on miss, loads from DB and populates cache | General purpose; good for read-heavy workloads |
| Write-through | Writes go to cache and DB simultaneously | Ensures cache is always fresh; write latency is higher |
| Write-behind | Writes go to cache immediately; DB is updated asynchronously | Lowest write latency; risk of data loss on cache failure |
| Read-through | Cache fetches from DB on miss automatically | Transparent to application code |
Database Choice Guide
| Use case | Database type | Examples |
|---|---|---|
| Structured data, ACID transactions | Relational (RDBMS) | PostgreSQL, MySQL |
| High-scale key-value lookups | Key-value store | Redis, DynamoDB |
| Flexible document storage | Document DB | MongoDB, Couchbase |
| Social graphs, recommendations | Graph DB | Neo4j, Amazon Neptune |
| Time-series metrics, monitoring | Time-series DB | InfluxDB, TimescaleDB |
| Full-text search | Search engine | Elasticsearch |
Consistent Hashing
Used for distributing data across nodes (servers or cache instances) in a way that minimizes data movement when nodes are added or removed.
Why it matters: If you have 10 cache nodes and one fails, simple modulo hashing (key % 10) remaps nearly all keys — a thundering herd hits the database. Consistent hashing remaps only 1/10 of keys.
Worked Examples
Design a URL Shortener
Requirements:
- Create a short URL from a long URL
- Redirect short URL to original URL
- ~100M URLs created/day; 10:1 read-to-write ratio
Key design decisions:
- ID generation: Use a Base62 encoding of a distributed counter (e.g., from a database sequence) or a hash — 7-character Base62 gives 62^7 ≈ 3.5 trillion unique URLs
- API:
POST /shorten {url}→{shortUrl},GET /{shortCode}→ 301/302 redirect - Storage: URL mapping table in a relational DB (ID, shortCode, originalUrl, createdAt, expiresAt)
- Caching: Cache hot short codes in Redis (most URLs follow a power-law distribution — a small % gets 90%+ of traffic)
- Redirect type: 301 (permanent, browser caches) vs 302 (temporary, counts every request for analytics)
Design a Chat System (WhatsApp/Slack Scale)
Key challenges:
- Real-time delivery: Use WebSockets (persistent connection from client to server)
- Message ordering: Use a monotonically increasing sequence number per conversation
- Offline delivery: Store messages in a queue; deliver on reconnection
- Storage: Time-series data (conversationId + timestamp as composite key in Cassandra works well for fan-out reads)
- Group messages: Fan-out on read (single stored copy, read by many) vs. fan-out on write (copy per recipient) — WhatsApp uses fan-out on read; Twitter timeline uses fan-out on write for most users, fan-out on read for celebrity accounts
What to Study
Books:
- Designing Data-Intensive Applications by Martin Kleppmann — essential
- System Design Interview by Alex Xu — practical interview prep
Online:
- System Design Primer on GitHub — free comprehensive reference
- Grokking the System Design Interview on Educative
