How Would You Design a URL Shortener?
Learn how to design a scalable URL shortener, covering key generation, caching, key-value storage, and handling billions of redirects in interviews.
Expected Interview Answer
A URL shortener maps long URLs to short, unique codes by hashing or base-62 encoding an auto-incrementing ID, storing the mapping in a key-value store, and redirecting with an HTTP 301/302 on lookup.
The write path takes a long URL, generates a compact unique key (via a counter converted to base-62, or a hash with collision checks), and stores {shortKey: longUrl} in a fast key-value database such as Redis or DynamoDB, fronted by an API server. The read path looks up the key on GET /{shortKey} and issues a redirect, so reads vastly outnumber writes and should be cached aggressively (CDN or in-memory cache) since URLs rarely change after creation. At scale you shard the key space across database nodes, use a distributed ID generator (like Snowflake) to avoid a single counter bottleneck, and add rate limiting plus analytics logging asynchronously so it never blocks the redirect.
- Simple read-heavy workload that caches well
- Base-62 encoding keeps keys short and URL-safe
- Horizontally scalable with sharded key-value storage
- Cheap to add analytics without slowing redirects
- Clear separation of write path and read path
AI Mentor Explanation
A URL shortener is like a scorecard that replaces a long ball-by-ball commentary with a short code such as 'W' for wicket or '4' for boundary, and anyone reading the scoreboard instantly knows which full event it stands for. The board keeps a compact lookup of codes to events, updates it once per ball.
Step-by-Step Explanation
Step 1
Define the API contract
POST /shorten accepts a long URL and returns a short code; GET /{code} redirects to the original URL.
Step 2
Generate a unique short key
Use a distributed counter converted to base-62, or hash the URL and resolve collisions, to produce a 6-8 character key.
Step 3
Store the mapping
Persist {shortKey: longUrl, createdAt, expiresAt} in a fast key-value store like Redis or DynamoDB for low-latency lookups.
Step 4
Cache aggressively for reads
Front the redirect path with a CDN or in-memory cache since reads vastly outnumber writes and URLs rarely change.
Step 5
Scale and add analytics
Shard storage by key prefix, use a distributed ID generator to avoid write bottlenecks, and log clicks asynchronously.
What Interviewer Expects
- Distinguishes the write path (shorten) from the read path (redirect)
- Proposes a concrete key-generation scheme (base-62 counter or hash)
- Chooses a key-value store suited to high read throughput
- Mentions caching since reads dominate writes
- Discusses scaling: sharding, distributed IDs, avoiding single points of failure
Common Mistakes
- Using an incrementing integer directly as the visible short code
- Forgetting that reads vastly outnumber writes and skipping caching
- Ignoring collision handling when hashing URLs
- Not considering custom aliases or expiry as follow-up requirements
Best Answer (HR Friendly)
“A URL shortener takes a long web address and gives it a short, easy-to-share code, then instantly sends visitors to the original page when they click it. Behind the scenes it stores a simple lookup table, generates unique short codes, and caches popular links so redirects happen almost instantly even at huge scale.”
Code Example
ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode(num: int) -> str:
if num == 0:
return ALPHABET[0]
digits = []
base = len(ALPHABET)
while num:
num, rem = divmod(num, base)
digits.append(ALPHABET[rem])
return "".join(reversed(digits))
# counter=125 -> compact, URL-safe short key
short_key = encode(125)
print(short_key)Follow-up Questions
- How would you handle custom (vanity) short codes?
- How do you prevent short-key collisions at high write volume?
- How would you add link expiry and analytics without slowing redirects?
- How would you shard the database as the URL count grows to billions?
- How do you protect the service from abuse or spam link creation?
MCQ Practice
1. Why is caching especially important for a URL shortener?
Since every click triggers a lookup but shortening happens once, reads dominate and benefit greatly from caching.
2. What does base-62 encoding a counter achieve?
Base-62 uses digits and both letter cases to pack a large counter value into a short, URL-safe string.
3. Which HTTP status is typically used to redirect a short URL?
301 (permanent) or 302 (temporary) redirects tell the browser to fetch the original long URL.
Flash Cards
Why do URL shorteners favor key-value stores? — Lookups are simple key-to-value reads that need very low latency at high volume, which key-value stores optimize for.
What problem does a distributed ID generator solve here? — It avoids a single counter becoming a write bottleneck or single point of failure as traffic scales.
Why cache the redirect path? — Reads vastly outnumber writes and URLs rarely change, so cached lookups avoid hitting the database repeatedly.
What is a collision in this context? — Two different long URLs hashing to the same short key, requiring a retry or salt to resolve.