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.
Free full guide
Design a scalable URL shortener for 100M daily active users.
The interview rhythm stays compact, so the page can spend attention on the actual design decisions.
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.
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. This read path is the hot path the whole design serves; click events are emitted asynchronously, off 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 - which stresses code allocation, never the redirect path.
05Can a link be retargeted to a new destination after creation?
Links are immutable by default; retargeting is an explicit optional feature, and using it must invalidate every cache layer holding the old destination.
06Who owns a link - can creators list and deactivate their own?
Links belong to their creator: list, deactivate, and retire - a deactivation propagates to caches within seconds, not at TTL expiry.
Out of scopeAnalytics dashboard — only async click-event emission stays in scope · User accounts, auth, and link-management UI · Spam and malicious-URL scanning
01What read/write ratio should I assume — is this heavily read-skewed?
Read-heavy: at least 100:1 redirects to creates, and marketing-heavy deployments run closer to 1000:1 — ask which, then design the redirect path cache-first either way.
02How fast must a redirect feel to the user?
Redirect p95 under 100 ms — a cache hit answers in single-digit milliseconds, so the extra hop feels invisible.
03Must a brand-new link resolve instantly everywhere, or is a short delay fine?
Availability over consistency: 99.99% for redirects; a just-created link may take seconds to propagate to caches and replicas (eventual consistency accepted).
04How many total links should the code space and storage plan for?
Plan for ~1B links: 7-char base62 gives 62^7 ≈ 3.5 trillion codes 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, allocation must not be sequentially predictable: enumerable base62 codes leak private URLs, so randomize within allocated ranges.
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.
Treat every estimate as a pressure that justifies a component: cache, queue, partition, replica, worker pool, or fallback path.
Redirect read QPS
100M DAU × ~1 redirect each per day100,000,000 ÷ 86,400 s ≈ 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.
Create write QPS
~1M new links per day1,000,000 ÷ 86,400 s ≈ 12 writes/s
Writes are trivial: no write scaling needed — the only write-side risk is code allocation contention, not row inserts.
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.
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.
Cache size
Top ~20% of links serve ~80% of reads (Pareto)20% × 1 TB ≈ 200 GB
Feasible on a modest Redis cluster; the hottest viral links additionally sit on the CDN edge.
Decision example
The numbers say one thing: reads outnumber writes about 100 to 1 and peak at 5-10K redirects per second, with under 100 ms to answer — so the redirect is the only path worth optimizing.
I would answer redirects from a cache first (Redis, plus CDN for the hottest links), so 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 — creating a link never fights over a shared counter. Clicks get counted by dropping an event onto a stream; the redirect never waits for analytics.
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.
If accurate per-click analytics becomes a must-have, I would switch from 301 to 302 redirects: browsers stop caching the hop, every click reaches my servers and gets counted, and I accept the small extra latency.
Draw the write path and the read path as separate lanes — they carry different traffic and justify different components.
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.
KGS hands out pre-generated unique code ranges, so creates never collide and never block on a shared counter.
Cache miss falls back to the database and refills the cache; click events go to the analytics stream off-path.
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
ShortLinkshort_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.
Useruser_id (PK) · email · created_at
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.
FocusHow short codes get made
AskHow do you guarantee two links never get the same code — counter + base62, or hashing? Why that one?
AvoidHashing the URL and hoping collisions are rare, without explaining the uniqueness guarantee.
FocusMaking the redirect fast
AskWalk one redirect end to end: where does the cache hit, what happens on a miss, and when does the database actually get touched?
AvoidReading the database on every redirect — the hot path must be cache-first.
Focus301 or 302
AskWhich redirect status do you return, and what does that choice do to browser caching and your click data?
AvoidPicking one arbitrarily — this choice IS the analytics decision.
FocusCounting clicks without slowing redirects
AskHow do you record clicks for 100M DAU without adding latency, and what happens if the analytics pipeline falls behind?
AvoidWriting analytics synchronously inside the redirect.
FocusOne link goes viral
AskA single link suddenly takes 10% of all traffic — what breaks first, and how do cache and CDN absorb it?
AvoidAssuming traffic is evenly spread — hot keys are the real load.
Talk through URL Shortener out loud and get AI scoring on the explanation.