URL Shortener
The problem
Design a URL shortener (like TinyURL or bit.ly). A user pastes in a long URL and gets back a short link; when someone visits the short link, they're redirected to the original.
Clarifying questions
Before designing anything I’d want answers to:
- Does the link expire? Because it affects the immutability. Permanent by default, with an optional user-set expiry.
- Can a user create Custom Aliases? Because it affects uniqueness of each generated link. Optional. Aliases must be globally unqiue and reject on collision.
- Is analytics for redirection in scope?Yes.
- What if the same URL is submitted for shortening more than once? Because it affects analytics for redirection. Mint a fresh short code each time so analytics can remain separate.
Actors & Requirements
Actors
- Creator / Shortener - submits a long URL, receives a short link.
- Visitor / Clicker - follows the short link and is redirected.
- Analytics Consumer - usually the creator returning later to see click stats.
- (Optional - Real World) Preview Crawlers - WhatsApp/Slack/iMessage bots that fetch the link to build a preview card. Uses the direct path, but useful to know.
Functional requirements
- The system must…
- Create a short link from a long URL.
- Redirect a short link to its original URL.
- Track and report click analytics for a link.
Non-functional requirements
- Ready Heavy: roughly 100:1 Read:Write ratio, drives caching and storage.
- Latency: redirect p99 under 100 ms (latency)
- Throughput: High Requests / sec.
- CAP -> AP: Favour availability because mappings are immutable, so no write conflicts. Note: The write path (alias uniqueness) needs stronger consistency.
- Durability: High. Never lose a mapping, that's the core functionality.
- Availability Target: 99.9%+.
Back of the envelope
| Metric | Estimate | Notes |
|---|---|---|
| Daily active users | X M | Assumption or source |
| Peak writes/sec | ~X k | How you derived it |
| Peak reads/sec | ~X k | Read:write ratio |
| Storage per year | ~X TB | Avg object size × write rate |
| Bandwidth (inbound) | ~X Gbps | Avg payload × writes/sec |
STATE THE ONE SCALE CONCLUSION that shapes the design — e.g. “X k writes/sec means we can’t afford a single SQL writer.”
High-level design
NARRATIVE OVERVIEW — one paragraph describing the system end to end before going deep.
Component: API Gateway
What it does and why it sits here.
Component: Key Generation Service (KGS)
What it does and why it sits here.
Component: URL Shortener, URL Redirection, Anayltics Services
What it does and why it sits here.
Component: Cache
What it does and why it sits here.
Component: Database
What it does and why it sits here.
Component: Queuing
What it does and why it sits here.
Low-level design
WHICH COMPONENT are you going deep on, and why this one over the others.
Data model
TABLE / SCHEMA NAME
field_name TYPE -- note
field_name TYPE -- note
Critical path: NAME
Walk through the most important sequence step by step.
- Step one.
- Step two.
- Step three.
Risks & trade-offs
None of these are blockers. They’re things I’d want a decision on before we shipped.
- RISK. Explanation and mitigation.
- RISK. Explanation and mitigation.
- RISK. Explanation and mitigation.
OPTIONAL CLOSING THOUGHT — a one-liner that captures the core judgment call.
What I’d actually recommend
SUMMARY RECOMMENDATION in 2-3 sentences. What to build, what to defer, and what to write down.
Filed under: TAG, TAG. Got a sharper take or a war story? Tell me.