Step 1: Ask before you draw
Don’t start drawing boxes. Interviewers leave the question vague on purpose, to see whether you ask what matters. Spend the first few minutes agreeing on what you’re building:
- What must it do? Create a short link from a long URL. Redirect a short link to the long one. Maybe: custom aliases (
sho.rt/winter-sale), links that expire, click counts. - How big? How many new links per day? How many clicks? The numbers decide the design.
- What matters most? Redirects must be fast and always work. Creating links can be a bit slower.
Write the answers down where the interviewer can see them. Every decision later points back to this list.
Pin down functional scope (create, redirect, custom alias, expiry, analytics, edit or delete?) and the non-functional shape: read/write ratio, latency target for redirects (p99 under ~50 ms server-side), availability (redirects are the product; creation can degrade), durability (a link must never point somewhere else), and abuse (it’s a phishing tool if you’re careless). Then state explicit non-goals so you can spend the time on the interesting parts.
For this walkthrough we’ll agree on: create and redirect, optional custom alias and expiry, click counts; 100 million new links per month, 100 reads for every write, links kept for 5 years.
Step 2: Estimate
| What | Calculation | Result |
|---|---|---|
| Writes | 100M per month ÷ ~2.6M seconds | ~40 per second (peaks ~200) |
| Reads | 40 × 100 | ~4,000 per second (peaks ~20,000) |
| Links stored | 100M × 12 months × 5 years | 6 billion |
| Storage | 6B × ~500 bytes (URL, code, dates, owner) | ~3 TB |
These are rough on purpose. The point isn’t the exact number; it’s the shape: this system reads far more than it writes, so the design should make reads cheap (hello, cache), and 3 TB doesn’t fit comfortably on one small database forever.
The conclusions to say out loud: read-heavy, so cache redirects aggressively; the hot set is small (a few percent of links get most clicks), so a modest Redis cluster absorbs most reads; ~3 TB plus indexes and replicas is past one comfortable node, so plan the partition key now (the short code) even if you start on one; writes are trivial, so the hard parts are ID generation, cache behavior and abuse.
Step 3: The API
POST /api/links
{ "url": "https://shop.example.com/products/winter-sale?campaign=newsletter-11", "alias": null, "expiresAt": null }
→ 201 Created
{ "code": "3fA9xQ", "shortUrl": "https://sho.rt/3fA9xQ" }
GET /3fA9xQ
→ 302 Found
Location: https://shop.example.com/products/winter-sale?campaign=newsletter-11How to talk through it in the interview
- Requirements (about 5 minutes): functional, scale, what matters most. Write them down.
- Estimates (about 3 minutes): reads, writes, storage. Name the conclusion: “read-heavy, so caching matters”.
- API (about 3 minutes): the two endpoints and their status codes.
- High-level design (about 10 minutes): draw the boxes and walk one request through them.
- Deep dives (the rest): short codes, caching, scaling the database. Let the interviewer pick, and always compare two options before choosing one.
Estimate a photo-sharing app
Practice the estimate step on a new system. A photo-sharing app has 10 million daily active users. Each user uploads 2 photos a day on average and views 50. A stored photo (with its smaller preview sizes) takes about 2 MB. Estimate:
- Uploads per second
- Views per second
- New storage per day, and for 5 years
Round freely: there are about 100,000 seconds in a day (86,400, rounded up).
›
Start from the day, then divide: 10M users × 2 photos = 20M uploads a day. Now divide by the seconds in a day.
›
For storage, multiply uploads per day by the size of one photo, then by about 365 × 5 ≈ 1,800 days. Write the units next to each number (MB, TB, PB) so you don’t lose a factor of 1,000.
SolutionTry it yourself first
| What | Calculation | Result |
|---|---|---|
| Uploads | 20M per day ÷ 100,000 s | ~200 per second (peaks ~1,000) |
| Views | 10M × 50 = 500M per day ÷ 100,000 s | ~5,000 per second (peaks ~25,000) |
| Storage per day | 20M × 2 MB | 40 TB |
| Storage for 5 years | 40 TB × 1,800 days | ~72 PB |
The conclusions are what the interviewer wants to hear:
- Views are 25× uploads, so it’s read-heavy: serve photos from a CDN, not from your servers.
- 72 PB is not a database job. Photos go to object storage (like S3); the database only keeps metadata: who uploaded what, when, and where the file lives.
- Peaks are about 5× the average (everyone posts on Saturday evening), so size for peaks, not averages.
- Numbers: 40 writes/s, 4,000 reads/s (100:1, peaks ~5×), 6B links, ~3 TB over 5 years.
- Say the conclusions: read-heavy, so cache redirects; a small hot set; past one comfortable node, so choose the partition key (the code) now. Name non-goals to save time for the hard parts.
Check this part
What should you do in the first few minutes of a system design interview?
The system has about 100 reads for every write. What does that suggest first?
Writes average 40 per second. What do you size the system for?
The estimate gives ~3 TB over 5 years. What design decision does that force early?