Home / System Design / Design a URL Shortener (TinyURL)

🔗 Design a URL Shortener (TinyURL)

Case Study ⏱ 8 min read

The URL shortener is the classic first system design question. It looks simple but touches key-generation, storage, caching and read-heavy scaling — a perfect way to apply the framework.

1. Requirements

  • Functional: shorten a long URL to a short one; redirect the short URL to the original; optional custom aliases and expiry.
  • Non-functional: very read-heavy (many redirects per create), low-latency redirects, high availability, links effectively permanent.

2. Scale estimate

Say 100M new URLs/month and a 100:1 read:write ratio. That's ~40 writes/sec and ~4,000 redirects/sec — clearly read-dominated, which screams caching and replicas. Over 5 years that's ~6B URLs, so a 7-character key gives plenty of room.

3. Short-key generation

Encode a unique ID in base62 (a–z, A–Z, 0–9). 62⁷ ≈ 3.5 trillion combinations — more than enough. Two common approaches:

  • Counter + base62 — a distributed unique ID (or ranges handed out to servers) encoded to base62. No collisions.
  • Random / hash — generate a random 7-char key and check for collisions before saving.

4. Data model & storage

A simple mapping table: short_key → long_url, created_at, expiry, user_id. Because it's just key lookups at huge scale, a key-value / NoSQL store fits well, though SQL works at moderate scale. The dataset shards cleanly on the short key.

5. The redirect path (make it fast)

A redirect is a read: look up the key, return a 301/302 to the long URL. Put a cache (Redis) in front of the DB — the hot links serve almost entirely from cache. Add read replicas and a CDN edge for global low latency.

6. Bottlenecks & extras

Discuss: unique ID generation without collisions, cache invalidation on expiry, analytics via an async queue (don't block the redirect to count clicks), and abuse/spam protection with rate limiting.

Frequently Asked Questions

Should a URL shortener use a 301 or 302 redirect?
A 301 (permanent) lets browsers cache the redirect, reducing load but making click analytics harder. A 302 (temporary) routes every click through your server so you can count it. Many shorteners use 302 for analytics.
How do you generate unique short keys?
Encode a unique numeric ID in base62 to get a short alphanumeric key with no collisions, or generate random keys and check for collisions before saving. Base62 with 7 characters yields trillions of combinations.