Design a URL shortener
Design a service that turns a long URL into a short one and redirects on lookup.
Assume 100M new links a month and a 100:1 read-to-write ratio. Before drawing anything, write down the numbers those figures imply — the interviewer is watching whether you size the problem or start naming databases.
Solution
Sizing first. 100M writes/month is ~40/s average, call it 200/s at peak. Reads at 100:1 are ~4k/s average, ~20k/s peak. At ~500 bytes a row, 100M rows/month is ~50GB/year — small. This matters because it tells you the write path is trivially servable by one database and the entire design problem is the read path.
The key generation choice, which is the real content of the question:
- Hash the URL and truncate. Deterministic and stateless, but collides, so every write needs a read to check — and the same URL from two users gives one key, which breaks per-user analytics.
- Random 7-character base62. 62^7 ≈ 3.5 trillion keys. Needs a uniqueness check on write, but at 200/s with an indexed unique constraint that is free. Unguessable, which matters if links are semi-private.
- Counter, base62-encoded. No collisions by construction and no check needed, but sequential keys are enumerable — anyone can walk the whole corpus. Fixable by encrypting the counter, at which point you have complexity without much gain.
Random-with-uniqueness-constraint is usually right, and saying why the alternatives lose is the answer.
Read path. Redirects are a cache-hit workload with an extremely skewed distribution — a tiny fraction of links take most of the traffic. Cache aggressively; mappings are immutable once created, so there is no invalidation problem, which is the single nicest property of this system and worth naming. 20k/s against a cache is unremarkable.
Storage. A key-value shape with one lookup by short code. Any store works; shard by the short code when it eventually needs it. Do not shard on day one.
301 vs 302. A 301 is cached by the browser, which is cheaper for you but means you stop seeing the traffic — no click analytics and no ability to change or revoke a link. 302 keeps control. If the product sells analytics, that decision is already made for you.
Where it gets interesting: custom aliases (a uniqueness race against a hot namespace), expiry and deletion, abuse and phishing, and rate limiting per creator.
The follow-up they will ask
A user wants a custom alias. What breaks, and how do you handle two users requesting the same one at the same moment?