System DesignIntermediate

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

Strong green flag · Points out that 301 breaks analytics and that click tracking must be asynchronous, before being asked.
Green 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
Red flags
  • "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

Follow-up questions

F1
Why not a single auto-increment counter?
F2
Someone scripts random codes at 10k req/s. What happens?
F3
When would you shard the database?

Scenario

A candidate opens with "I would use an API gateway, a URL microservice, a redirect microservice, Kafka for events and Cassandra for storage." You ask how many URLs are created per day; they do not know. Guide them: what should they have asked, what do the numbers say, and where does the first real architectural decision actually lie?

Learn this topic