Systems Thinking
← All writing

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
The number that drives everything

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.

High-level architecture diagram
CAPTION — e.g. “Request flow from client through gateway to storage layer.”

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.

Low-level design diagram
CAPTION

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.

  1. Step one.
  2. Step two.
  3. 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.