Design a URL Shortener

Beginner · 25 min read · High-Level Design, Case Studies: Core

Key generation, redirects at scale, caching and analytics.

A URL shortener (bit.ly, TinyURL) turns https://example.com/blog/2026/10/a-very-long-article-title?utm_source=newsletter into https://sho.rt/x7Kp2Qa, and redirects anyone who visits the short link.

1. Clarify the problem

Questions worth asking, and the answers we'll assume:

2. Requirements

Functional

3. Capacity estimation

So: writes are tiny. Reads are moderate but must be fast → cache aggressively. 3 TB of link data fits comfortably in a horizontally scalable KV store (or a sharded relational DB). Analytics is the largest data stream and should be decoupled from the redirect path.

4. API

Rate-limit POST /v1/links per API key and per IP — URL shorteners are prime spam/phishing tools.

5. Data model

The access pattern is a pure key lookup by code, with no joins on the hot path. Good choices: DynamoDB/Cassandra (partition key = code, scales horizontally, multi-region replication) or PostgreSQL/MySQL sharded by code (strong uniqueness, familiar).

6. High-level design

Create flow

7. Deep dives

Option A — hash the long URL (e.g., first 7 Base62 characters of SHA-256 or MD5).

8. Failure modes and scaling

9. Trade-offs summary

10. What interviewers look for

Interview questions

  • Two users shorten the same long URL. Should they get the same code?
  • A link goes viral and receives 500,000 requests per second. What breaks and how do you handle it?
  • How do you prevent people from guessing other users' short links?
  • Your key range allocator is a single database row. Isn't that a bottleneck?

Practice

Write your answer before opening the suggested one. Anything you mark "Partly" or "Missed it" comes back in your review deck.

Further reading

Key takeaways

  • A URL shortener is read-heavy and latency-sensitive: cache in Redis and at the edge, keep analytics asynchronous.
  • 7 Base62 characters give ~3.5 trillion codes — plenty for billions of links with a sparse, unguessable space.
  • Generate codes with random + conditional insert, or range-allocated counters through a permutation; avoid enumerable sequences.
  • Use 302 when analytics and deletion matter; 301 only to minimise load.
  • Plan for viral links, expiry, abuse and multi-region reads.

Previous: Security Fundamentals · Next: Design a Distributed Rate Limiter