System Design Problems interview question · Most asked
Design a URL shortener (like bit.ly).
Summary
Generate short unique codes mapped to long URLs, serve redirects with very low latency from a cache, and record click analytics asynchronously. Reads dominate writes (~100:1), so the redirect path is cache-first.
Requirements
- Create a short link for a long URL (optional custom alias, expiry)
- Redirect short → long with low latency (p99 < 50 ms)
- Click analytics per link
- Non-functional: highly available reads, links never collide, 100M new links/month
Back-of-the-envelope
- 100M links/month ≈ 40 writes/s; 100:1 reads ≈ 4,000 redirects/s (peaks 10×)
- ~500 bytes/link → ~600 GB over 10 years
- 7-character base62 codes give 62^7 ≈ 3.5 trillion combinations
API
POST /api/links {"url": "https://...", "alias": "optional", "expires_at": "optional"}
→ 201 {"code": "aZ3kP9q", "short_url": "https://sho.rt/aZ3kP9q"}
GET /{code} → 301/302 Location: https://...
GET /api/links/{code}/stats → {"clicks": 1234, "by_day": [...]}
Data Model
links(code PK varchar(10), long_url text, owner_id bigint, created_at, expires_at)
clicks(code, ts, country, referrer, ua_family) -- append-only, in an analytics store
Architecture
Clients hit a CDN/edge, then stateless API servers. Redirects read from Redis (code → URL) with a database fallback (a key-value store or Postgres keyed by code). Link creation obtains a unique ID and encodes it in base62. Click events are pushed to a queue (Kafka) and aggregated by stream processors into an analytics store (ClickHouse).
Deep Dives
- Code generation: a counter-based ID (range allocation per server from a sequence/ZooKeeper/DB) encoded in base62 avoids collisions; random codes need a uniqueness check; hashing the URL needs collision handling
- 301 vs 302: 301 is cached by browsers (less load, fewer analytics); 302 keeps every click visible
- Custom aliases: reserved words, uniqueness via unique constraint
- Abuse: malware URL scanning, rate limits per user/IP
Scaling
- Cache hot codes in Redis and at the edge; hit ratios above 90% are typical
- Shard the links store by code
- Analytics writes go through a queue, never in the redirect path
- Multi-region read replicas for global latency
Comparison / Tradeoffs
| Decision | Option chosen | Alternative | Why |
|---|---|---|---|
| Code generation | Counter + base62 | Random or hash | No collisions, short codes; counters are predictable (add salt/shuffle if needed) |
| Redirect status | 302 | 301 | Accurate analytics over fewer requests |
| Storage | Key-value / Postgres by PK | Graph or document DB | Simple primary-key access pattern |
Explanation
What interviewers look for
A structured approach: clarify requirements and scale, sketch the API and data model, draw the high-level architecture, then go deep on the hardest component and discuss trade-offs, bottlenecks and failure modes.
Follow-up questions
- How would you prevent enumeration of codes?
- How do you expire links and reclaim codes?
- How do you count unique visitors?
More most-asked System Design Problems questions
- Design a distributed rate limiter.
- Design a chat application (like WhatsApp or Slack).
- Design a social media news feed (like Twitter/X or Instagram).
- Design a notification system (email, SMS, push).
- Design a payment system.
- Design a ticket booking system (like Ticketmaster).
- Design a distributed unique ID generator.
- Design a webhook delivery system.