Free full guide

URL Shortener

Design a scalable URL shortener for 100M daily active users.

00

Practice checkpoints

The interview rhythm stays compact, so the page can spend attention on the actual design decisions.

  1. 01
    Clarify scope
  2. 02
    Requirements + scale
  3. 03
    API + data model
  4. 04
    Draw architecture
  5. 05
    Deep dive
  6. 06
    Trade-off decision
01

Requirements that shape the design

Do not only state requirements. Ask for them. Each card pairs the design constraint with a clarification question you can say out loud before drawing the architecture.

Functional requirements

01Should users be able to pick a custom alias, or is a system-generated short code enough?

Users can submit a long URL and get back a unique short link — system-generated base62 code (letters + digits) by default, custom alias as an optional extra.

02Do links live forever, or do we need expiration and cleanup?

Users can set an optional expiration; an expired link stops redirecting and its code can be retired later.

03Is the redirect itself the core flow — does anything else have to happen on click?

Anyone who opens a short link is redirected to the original URL — by far the most frequent operation. Every click must also be recorded, and recording must never delay the redirect.

04Do marketing campaigns need bulk creation - thousands of links in one call?

Support batch creation: a campaign mints thousands of links in one request.

05Can a link be retargeted to a new destination after creation?

Links don't change once created. Retargeting to a new destination is an optional extra. After a retarget, visitors must land on the new destination, never the old one.

06Who owns a link - can creators list and deactivate their own?

Links belong to their creator: list, deactivate, and retire — a deactivated link must stop redirecting within seconds.

Out of scopeAnalytics dashboard — only async click-event emission stays in scope · User accounts, auth, and link-management UI · Spam and malicious-URL scanning

Non-functional requirements

01What read/write ratio should I assume — is this heavily read-skewed?

Read-heavy: about 100M people follow a short link on a typical day, against about 1M new links created. That is at least 100:1 redirects to creates. Marketing-heavy deployments run closer to 1000:1, so it is worth asking which one this is.

02How fast must a redirect feel to the user?

Redirect p95 under 100 ms — the short-link hop must feel invisible to the person clicking.

03Must a brand-new link resolve instantly everywhere, or is a short delay fine?

Availability over consistency: redirects target 99.99%. A just-created link may take a few seconds to reach every cache and replica (eventual consistency accepted).

04How many total links should the code space and storage plan for?

Plan for ~1B links. A 7-char base62 code gives 62^7 ≈ 3.5 trillion possible codes, plenty of headroom. At ~1 KB per row, total storage stays near 1 TB, shardable by short code.

05Can two links ever share a code — and can someone guess private codes?

Short codes must be globally unique — no collisions, ever. For private links, codes must not be guessable: a predictable sequence would let a stranger enumerate private URLs one by one.

Keep asking — the interview is a conversation

Real interviews probe far more than a tidy list. These are the scope questions that separate candidates who interrogate the problem from those who recite it.

  • How long must click history be kept — and do dead links need to stay queryable for audits?
  • Can anyone create links without an account, or do we need per-user limits to keep abuse in check?
  • Do customers want short links under their own branded domains, or only ours?
  • Where do the users live — should redirects be equally fast worldwide, or is traffic concentrated in one region?
  • Do click records count as personal data — any privacy rules on what we may store and for how long?
02

Numbers that force architecture decisions

Treat every estimate as a pressure that justifies a component: cache, queue, partition, replica, worker pool, or fallback path.

01

Redirect read QPS

100M daily users (the read-heavy sizing above) × ~1 redirect each per day = 100M redirects/day100,000,000 redirects ÷ 86,400 s in a day ≈ 1,160 QPS average · viral bursts ×5-10 ≈ 5-10K QPS peak

Cache + CDN must absorb the peak — the database never serves the redirect hot path.

02

Create write QPS

~1M new links per day1,000,000 ÷ 86,400 s ≈ 12 writes/s

Writes are trivial, so no write scaling is needed. The one write-side risk is fighting over code allocation, not the row inserts.

03

Total storage

1B links × ~1 KB per row (code, long URL, owner, timestamps, TTL)10⁹ × 1 KB ≈ 1 TB

Fits a sharded store comfortably; the short_code index is the real working set.

04

Code space

7-character base62 codes (62 characters per position)62⁷ ≈ 3.5 × 10¹² codes vs 10⁹ links needed → ~3,500× headroom

Codes never run out — the real risk is predictability (enumerable codes), not exhaustion.

05

Cache size

Assume ~20% of links serve ~80% of reads (Pareto)20% × 1 TB ≈ 200 GB

Feasible on a modest Redis cluster. The hottest viral links also sit on the CDN edge.

Decision example

The numbers

The numbers point one way. Reads outnumber writes about 100 to 1, and peak at 5-10K redirects per second, each with under 100 ms to answer. So the redirect is the only path worth optimizing.

My choice

Answer redirects from a cache first — Redis, plus CDN for the hottest links. That way the database is never in the hot path. For creating links, a small key service hands each API server a batch of pre-made unique codes, so a create never fights over a shared counter. Clicks get counted by dropping an event onto a stream. The redirect never waits for analytics.

Avoid

What I would NOT do: hash the long URL to make the code and retry whenever two URLs collide. Under load those retries pile up and creating a link becomes a lottery. Handing out pre-made unique codes makes collisions impossible instead of merely unlikely.

Change if

If accurate per-click analytics becomes a must-have, I would switch from 301 to 302 redirects. Then browsers stop caching the hop, so every click reaches my servers and gets counted. I accept the small extra latency.

03

Architecture path

One complete picture first, then each path as its own diagram — the write path and the read path carry different traffic and justify different components.

Complete picture

Overview — every component

ClientCDN / EdgeAPI ServiceCacheDatabaseKey GenerationServiceget code rangesAnalytics Streamasync click events

Start with the simple version: one picture, every component and relation. Dashed = asynchronous, off the hot path. A cache miss falls back to the database and refills the cache.

Path 1

Write path — create a short link

ClientAPI ServiceKey GenerationServiceDatabaseCache (pre-fill)

KGS hands out pre-generated unique code ranges, so creates never collide and never block on a shared counter.

Path 2

Read path — redirect (the hot path)

ClientCDN / EdgeAPI ServiceCache301/302 Redirect

Cache miss falls back to the database and refills the cache; click events go to the analytics stream off-path.

04

API and data model

Before optimizing, make the contract inspectable: endpoints, entities, ownership, retries, and state.

POST/urls

req{ long_url, custom_alias?, expires_at? }

res200 { short_url, expires_at } · 409 alias taken · 400 invalid URL

Idempotent per (owner, long_url): resubmits return the existing short_url instead of minting a new code.

GET/{short_code}

res301/302 + Location: long_url · 404 unknown code · 410 expired

301 lets browsers cache the redirect (fewer origin hits, loses click analytics); 302 sends every click through your servers (keeps analytics, adds a hop). The choice hangs on the analytics requirement — say it out loud.

Core entities

ShortLink

short_code (PK) · long_url · owner_id · created_at · expires_at · is_active

Shard by short_code so a redirect hits exactly one partition; an optional inverted index long_url → short_code enables create-time dedup.

User

user_id (PK) · email · created_at

05

Deep dive directions

Pick one lane for the final third of the interview. Each lane gives you the topic, the interviewer question it should answer, and the failure mode to avoid.

Focus

How short codes get made

Ask

How do you guarantee two links never get the same code — counter + base62, or hashing? Why that one?

Answer

Pre-mint the codes; don't hash. A separate service makes unique codes ahead of time and gives each API server its own block to hand out. Two servers can't pick the same code, and no one has to check the database first — even during a big campaign. Hashing only makes clashes rare, and every clash costs a retry when load is highest.

Avoid

Hashing the URL and hoping collisions are rare, without explaining the uniqueness guarantee.

Focus

Making the redirect fast

Ask

Walk one redirect end to end: where does the cache hit, what happens on a miss, and when does the database actually get touched?

Answer

Read the code from Redis first. A cache hit answers in a few milliseconds and never touches the database; a miss reads it once, then refills the cache. The hottest links also sit on the CDN edge. When a link is killed or retargeted, don't wait for the TTL — delete it from Redis and purge the CDN copy right away, so the change takes effect in seconds.

Avoid

Reading the database on every redirect — the hot path must be cache-first.

Focus

301 or 302

Ask

Which redirect status do you return, and what does that choice do to browser caching and your click data?

Answer

Use 302 here, because we have to count every click. A 302 makes the browser ask the server each time, so every click is seen — the cost is one extra hop. A 301 lets the browser cache the redirect forever: faster, but repeat clicks go invisible. Since counting clicks is a requirement, 302 wins.

Avoid

Picking one arbitrarily — this choice IS the analytics decision.

Focus

Counting clicks without slowing redirects

Ask

How do you record clicks for 100M DAU without adding latency, and what happens if the analytics pipeline falls behind?

Answer

The redirect drops a click event onto a durable stream like Kafka and returns immediately — the counting happens afterward, off to the side. If that pipeline falls behind, counts go stale for a while, but redirects never slow down. Stale numbers are an acceptable trade; slow redirects are not.

Avoid

Writing analytics synchronously inside the redirect.

Focus

One link goes viral

Ask

A single link suddenly takes 10% of all traffic — what breaks first, and how do cache and CDN absorb it?

Answer

A single viral link overloads the one cache shard that holds it, long before the database notices. Serve it from the CDN edge with a short TTL, so millions of hits are soaked up before they reach us. API servers can also keep it in local memory as a backup. However hard one link spikes, origin traffic stays flat.

Avoid

Assuming traffic is evenly spread — hot keys are the real load.

Ready to practice?

Talk through URL Shortener out loud and get AI scoring on the explanation.

Practice this with AI →