System design interviews terrify most developers because the problem space is unbounded. “Design Twitter.” “Design a URL shortener.” “Design a distributed caching layer.” Where do you even start?
After conducting 100+ technical interviews and mentoring engineers through FAANG and MAANG prep, I’ve distilled the process into a repeatable framework. Here it is.
The 6-Step Framework
Step 1: Clarify Requirements (5 minutes)
Never start designing without asking these questions:
- Scale: How many users? Read-heavy or write-heavy? Expected QPS (queries per second)?
- Consistency vs availability: Is it okay to serve slightly stale data? Can we lose writes?
- Geography: Single region or global?
- SLAs: What’s the acceptable latency? Uptime requirement?
Most candidates skip this and start drawing boxes. Interviewers notice. The senior engineer asks questions first.
Step 2: Define the API Contract
Before any infrastructure, define what the system exposes:
POST /urls
Body: { "long_url": "https://example.com/very-long-path" }
Response: { "short_code": "abc123", "short_url": "https://short.ly/abc123" }
GET /{short_code}
Response: 301 Redirect to long_url
This forces you to think about the user-facing contract before implementation details.
Step 3: Estimate Scale (Back-of-Envelope)
Do the math out loud:
- “100M URLs created per day = ~1,200 writes/second”
- “10:1 read/write ratio = 12,000 reads/second”
- “Average URL ~500 bytes, 100M/day × 365 days × 500 bytes = ~18TB/year”
You don’t need exact numbers. You need to demonstrate that you think in orders of magnitude.
Step 4: Design the Data Model
SQL vs NoSQL is almost always the first real decision:
| Factor | Lean SQL | Lean NoSQL |
|---|---|---|
| Strong consistency needed | ✅ | ❌ |
| Complex joins / reporting | ✅ | ❌ |
| Horizontal scale to 100M+ rows | Harder | ✅ |
| Schema is stable | ✅ | Either |
| Access pattern is key-value | Either | ✅ |
For a URL shortener, a simple key-value store (Redis or DynamoDB) for the lookup is correct. Metadata (creation time, click analytics) can go in PostgreSQL.
Step 5: Design the System Components
Draw the boxes and explain each:
Client → CDN/Load Balancer → API Servers (stateless)
→ Redis (short_code → long_url cache)
→ PostgreSQL (metadata, analytics)
Then handle the hard parts:
- Short code generation: Base62 encoding of an auto-increment ID, or hash + collision handling
- Cache invalidation: TTL on Redis entries, write-through on creation
- Rate limiting: Per-IP, token bucket algorithm
Step 6: Address Bottlenecks and Trade-offs
This is where seniors separate from mids. Proactively discuss:
- Single points of failure: “The DB is a SPOF — we’d add read replicas and a primary failover”
- Hot partitions: “If a short URL goes viral, one Redis node gets hammered — consistent hashing distributes this”
- Cost vs performance: “CDN caching saves 90% of origin hits but adds stale redirect risk for deleted URLs”
What Interviewers Are Actually Evaluating
- Communication: Can you explain your thinking out loud?
- Systematic decomposition: Do you break problems into pieces?
- Trade-off awareness: Do you know there’s no perfect answer?
- Production mindset: Do you think about failure modes, not just happy paths?
They’re not testing whether you memorize architecture diagrams. They’re testing how you think.
The One Practice Exercise That Works
Take any app you use daily (Slack, Netflix, your bank’s mobile app). For 20 minutes, sketch on paper:
- What are the core entities?
- What’s the read/write ratio?
- Where are the bottlenecks?
- How would you scale to 10x current load?
Do this 20 times. You’ll stop being afraid of the blank whiteboard.
We cover system design thinking in Backend Architecture Foundations — the course that teaches you to think like a senior engineer before you become one.