Design a URL shortener at scale
What interviewers are testing
Interviewers want to see structured estimation before design: pinning requirements, deriving a 100:1 read:write ratio, and letting those numbers pick the architecture. The shortener also forces a real decision — ID generation strategy and 301 versus 302 — where every answer has a visible consequence for scale and analytics.
Mental model
URL shortening is a write-once, read-forever lookup: a key generator — a secret counter, a Snowflake, or random bytes encoded in base62 — produces the key, a key-value store is the source of truth, and caches at the edge absorb the 100:1 read traffic. Random keys are unguessable; counter and Snowflake keys are unpredictable only while the sequence state stays secret, and sequential values leak volume and ordering. The redirect status code is a product decision: 301 maximizes cacheability, 302 keeps every click visible to analytics.
Step-by-step solution
Step 1 of 5
Requirements and back-of-envelope math
Start by pinning requirements: shorten a long URL into a small one, redirect with minimal latency, and optionally support custom aliases, expiry, and click analytics. Then do the math out loud. Suppose 100 million new links per day; that is about 1,160 writes per second. Because a link is clicked roughly 100 times for every one created, reads land near 116,000 per second, a 100:1 read-to-write ratio. Seven base62 characters give 62^7, about 3.5 trillion keys, so a workload at this scale lasts decades. The estimate drives every later decision: the system is read-dominated, so caches, replicas, and CDN edges matter far more than write throughput, and the storage footprint stays trivial once you store only the mapping and a little metadata. Watch the animation as the request walks from the client through the stateless API tier while the read:write math sets the design priorities.
Animation — Requirements and back-of-envelope math
100:1 read:write
The client pastes a long URL; the API tier is stateless and scales horizontally.
Edge cases & traps
- Hash collisions in a hash-based generator silently overwrite a mapping: conditional-put the candidate key and retry with a salted input on conflict.
- Sequential base62 keys are guessable: shuffle the encoding alphabet, mix in a random salt, or add entropy — a plain Snowflake is time-ordered and unpredictable only while its sequence state stays secret.
- 301 responses bypass analytics entirely: use 302 or 307 when clicks must be counted, and reserve 301 for immutable links.
- Cache stampede on a viral link: add jittered TTLs and single-flight request coalescing so one miss cannot flood the KV store.
- Custom aliases and reserved words collide with generated keys: keep aliases in the same keyspace and reject reserved paths such as api, admin, and favicon.