Designing a URL shortener: the system design interview classic
January 21, 2025 · sydep team · 2 min read
The URL shortener is a system design interview staple for a reason: it's small enough to fully design in 45 minutes, but it touches ID generation, caching, storage trade-offs, and read/write scaling — a good proxy for how you reason about systems in general.
The core requirements
- Given a long URL, generate a short, unique key and store the mapping.
- Given a short key, redirect to the original URL with low latency.
- Reads vastly outnumber writes — short links get clicked far more often than they're created.
ID generation is the first real decision
Three common approaches, each with different trade-offs:
- Random string + collision check — simple, but requires a uniqueness check (and retry) on every write.
- Base62-encoded auto-increment counter — guarantees uniqueness for free, but a single global counter can become a write bottleneck at scale, and reveals roughly how many links exist.
- Pre-generated key ranges handed out to write nodes — the practical middle ground: a coordination service hands each writer a range of keys to consume, avoiding both the collision-retry problem and the single-counter bottleneck.
Why reads dominate the design
Because redirects vastly outnumber creations, the redirect path is where almost all of the engineering effort goes: an in-memory or CDN-edge cache in front of the primary key-value lookup, with the database as the fallback path for cache misses. Whether you reach for Redis, a CDN's edge KV store, or an in-process LRU cache depends on your latency budget and read volume — but the shape of the solution (cache-in-front-of-store) is the same at any scale.
Explore the full component layout — including where the cache sits relative to the redirect service and the ID generator — in the URL shortener reference.
What interviewers are actually probing for
Not whether you memorized "use Base62." They want to see you:
- Separate the write path (create short link) from the read path (redirect) explicitly, since they have very different traffic profiles.
- Reason about uniqueness without a naive "check and retry forever" loop.
- Identify caching as the lever that makes the redirect path fast, and know roughly where in the stack to put it.
- Talk about analytics (click counts, referrers) as an async, non-blocking side effect of the redirect — never on the critical path.
Once you've got the shape down on paper, it's worth dragging the actual components into a canvas and seeing how they connect — open this system in the app to explore it interactively.