System design · must-tier · asked at Amazon, Apple, Google, Meta, Microsoft, Netflix

Design a URL Shortener

mediumhldkey-generationstorage

Prompt

"Design a service like goo.gl: give me a short link for any long URL, and redirect anyone who hits the short link. Assume Google scale."

Clarifying questions

  • How short is short, and does the alphabet matter? Seven characters over base-62 (a-z, A-Z, 0-9) is fine. No offensive-word filtering needed for the first pass.
  • Can users pick a custom alias? Yes, optional. Custom aliases are a small fraction of traffic but must be unique.
  • Do links expire? Default never, with an optional TTL the creator can set.
  • Do we need click analytics? Basic counts per link. Full per-click logs are a follow-up, not the core.
  • Redirect type? 302 (temporary) so the browser keeps coming back and we can count clicks and honour deletions. 301 would be cached by browsers and cost us both.
  • Read/write ratio? Reads dominate heavily. Assume 100:1.
  • Any auth? Anyone can create; owners can delete or view stats. Treat auth as a solved dependency.
  • Latency target for redirects? Under 50 ms at the service, p99 under 200 ms end to end.

Requirements

Functional

  • Create a short link for a long URL; optionally supply a custom alias and a TTL.
  • Redirect a short link to its long URL.
  • Delete a link; expired or deleted links return 404 or a tombstone page.
  • Basic click counts per link.

Non-functional

  • Redirects must be highly available and low latency. A shortener with a slow redirect is useless.
  • Short keys must be globally unique; two long URLs must never map to one key.
  • Creation can tolerate slightly higher latency and eventual visibility across regions, within seconds.

Back-of-envelope

  • Assume 100 million new links per month. That is 100M / (30 × 86,400) ≈ 100M / 2.6M ≈ 40 writes/s average. Plan for 5× peak: 200 writes/s.
  • Reads at 100:1 → 4,000 reads/s average, 20,000 reads/s peak.
  • Storage per link: key (7 B), long URL (assume 200 B average, allow up to 2 KB), owner id (8 B), timestamps and flags (~30 B), plus index overhead. Call it 500 B per row with overhead.
  • Storage per year: 1.2 billion links × 500 B ≈ 600 GB/year. Over 10 years, 6 TB. That is one large database or a modest number of shards, not a big-data problem.
  • Key space: 62^7 ≈ 3.5 × 10^12. At 1.2 billion per year we use about 0.03% per year, so seven characters lasts effectively forever.
  • Bandwidth: redirect responses are tiny (a 302 with a Location header, maybe 500 B). 20,000 × 500 B ≈ 10 MB/s outbound. Not a concern.
  • Cache: the classic 80/20 rule says 20% of links get 80% of reads. Caching one day of reads: 4,000 × 86,400 ≈ 350M reads/day; if 20% of distinct links cover most of them, we want roughly 70M entries × 500 B ≈ 35 GB. That fits in a handful of cache nodes, or one region's Memorystore-style cluster.

Last reviewed 8 September 2026