Design a URL shortener
“Design a service like bit.ly. Walk me through requirements, scale, the API, the data model, and how the design evolves as traffic grows.”
What this tests
- Clarifying scope and estimating before drawing boxes
- ID generation: counter + base62 vs random vs hash, and collisions
- Read-heavy architecture: cache for hot redirects, 301 vs 302
- Evolving the design in response to numbers, not templates
Answers by level
Read the beginner answer first and notice what is missing.
Clarify first: custom aliases? expiry? analytics? Then estimate: 100 M new URLs a month ≈ 40 writes/s; reads 100× that ≈ 4,000/s, peaks 10× — a read-heavy system where a single database would cope on writes and the redirect path needs a cache. Storage: 100 M × ~500 bytes ≈ 50 GB/year, fine for one primary. API: POST /urls {long_url, alias?, expires_at?} → {code} and GET /{code} → 302 Location: long_url. Data model: urls(code PK, long_url, owner_id, created_at, expires_at); the code is the primary key, so the redirect is one indexed lookup.
ID generation is the interesting decision. Hashing the URL and truncating collides (birthday problem at 7 chars of base62 ≈ 3.5 T space is fine for uniqueness, but two users shortening the same URL get the same code — decide if that is a feature) and needs a collision check. A counter encoded in base62 never collides and produces 7-char codes up to 3.5 T ids, but a single counter is a bottleneck and leaks volume; hand out ranges of 1,000 ids per app instance from the database, or use a random 7-char code with a unique index and retry on the rare conflict. Then evolve: put Redis in front of the redirect (hot codes are Zipfian: 20% of codes take 80% of reads), then read replicas, then a CDN edge for the redirect itself.
Green flags · Red flags
- Clarifies scope (analytics, custom alias, expiry) before designing
- Does the arithmetic: writes/s, reads/s, storage per year
- Weighs counter + base62 vs random vs hash with collision handling
- Cache for hot redirects with negative caching
- Raises 301 vs 302 and its analytics consequence
- Adds components in response to a stated symptom
- "Load balancer, microservices and Kafka" before any number is on the whiteboard
- Truncated MD5 with no collision handling
- Writes the click event synchronously on the redirect path
- Cannot say whether one database would suffice