← Articulet System Design, Made Clear Chapter 13 · URL Shortener
Part 4 · Real Interview Systems Chapter 13

The URL shortener.

Turning a long destination into a tiny key and making redirects fast.

Learning objective
Design a URL shortener from scope to bottlenecks, including code generation, redirect reads, caching, and analytics, and explain the trade-offs in a calm, interview-ready way.
Before you read

Make a prediction first.

Predict

Answer before the explanation.

Which path matters more for a URL shortener: creating links or redirecting links?

Commit

Write a rough answer.

Before reading, draw two lanes: create short URL and redirect short URL.

Connect

Notice where it returns.

This design combines database lookup, caching, unique ID generation, analytics, and hot-key protection.

Plain English

The core job is small. That is why this is such a good interview system.

A URL shortener accepts a long URL, generates a short code, stores the mapping, and redirects readers quickly when they visit the short URL.

That simplicity is useful. It makes the real design questions easier to see. The system is not hard because there are many moving parts. It is hard because one path gets very hot and one correctness rule cannot be violated: the short code must point to the right destination, and two writers must not create the same code by accident.

Reasonable v1 scope
  • Create short URLs.
  • Redirect short code to long URL.
  • Optionally count clicks.
Layer on later
  • Custom aliases.
  • Expiration.
  • Abuse checks.
  • Analytics dashboards.
  • Account ownership.

The system has two main lanes: a write lane that creates the short URL, and a read lane that redirects quickly from short code to long URL. The read lane usually dominates. That one observation should shape the rest of the answer.

Why it matters in interviews

This prompt exposes whether you can separate the hot path from the side work.

Interviewers use URL shortener because it quickly reveals whether the candidate can scope cleanly, identify a read-heavy path, discuss uniqueness under concurrency, and keep analytics out of the critical response path.

Weak opener
We will use a database, a cache, and a load balancer.
Strong opener
The core read path is lookup by short code, so I want a very fast key-based lookup with caching in front of it. The write path must create unique codes without collisions. Analytics can be written asynchronously so the redirect path stays fast.

The stronger version names the hot path, the correctness rule, and the work that should move off the path. That is what makes it interview-useful.

Mental model

A short URL is a lookup key, not a compression trick.

Build a small, stable pointer. Then resolve it fast.
Long URL https://example.com/blog/a/b/c... GEN x7Ka9p Stored destination key to long URL what the user already has small, stable, addressable what the system stores
The system is not shrinking the web. It is creating a tiny stable key that resolves to stored truth.
Key ideas

Six anchors.

Core diagram

Two lanes and one side path are enough for the first diagram.

CREATE LANE REDIRECT LANE ASYNC SIDE PATH U User API accepts long URL Code generator unique short code R Reader Redirect service stateless, scalable Cache hot codes Mapping store code to long URL plus metadata 301 redirect click event Analytics queue Analytics processor
The redirect lane is the product. Everything else exists to keep that lane fast and correct.
Speaking script

Lines you can actually say out loud.

Opening
I will scope the first version to short URL creation and fast redirect lookups, then add analytics as a side path.
Sketching
The main read path is lookup by short code, so I want that to be a very fast key-based lookup with caching.
Deep dive
The main write concern is unique code generation across multiple servers.
Trade-off
I would keep the redirect path thin and move analytics off the critical path.
Extending
If custom aliases are in scope, I need collision checks and uniqueness rules for user-chosen codes as well.
Defending
The trade-off is usually a simple fast redirect path versus richer features like detailed analytics or stronger custom alias workflows.
Common mistakes

Predictable ways this answer goes wrong.

Misconception check

Correct the wrong model before it sticks.

Wrong intuition

What feels tempting

A URL shortener is a small CRUD app with a shorter string.

Better model

What to replace it with

The redirect path is the product. Creation can be slower; redirects must be fast, reliable, and cache-friendly.

Interview move

What to do in the room

Separate create path, redirect path, and analytics side path before deep diving on code generation.

Trade-offs

The decisions that come up every time.

ChoiceGood whenWeak whenInterview line
Generated codes Default You want predictable uniqueness and a clean write path. Users need meaningful custom aliases as a core feature. Generated codes keep the baseline write path simple and collision-safe.
Custom aliases Branding or memorability matters. Alias checks and collisions complicate the hot write path. Custom aliases are useful, but they add validation and uniqueness checks I would treat as a second step.
Inline analytics You need an immediately updated counter and traffic is small. Redirect latency matters and traffic is high. I would avoid blocking the redirect response on analytics writes.
Async analytics Default Fast redirect latency matters more than immediate analytics visibility. The product truly needs synchronous exact counters in the redirect path. Async analytics keeps the user-facing path fast while still preserving event data.
Central ID allocator Write scale is modest and the system is simple. The allocator becomes a bottleneck or a single hot dependency. I would use a central allocator only while write scale is still modest.
Distributed or range-based IDs Many servers create codes concurrently. The coordination logic is weak and collisions are still possible. At higher write scale, I want each writer to have a safe code-generation strategy without central contention.
Deep dive

How do many servers make unique short codes without colliding?

This is the correctness question in the system. The interviewer is listening for whether you can explain the contention shape, not whether you can drop a branded algorithm name.

Central allocator simple, but every writer queues on one dependency Writer A Writer B Writer C Writer D ID allocator single hot dependency Range-based or distributed each writer owns a slice, so writes do not coordinate per request Writer A 0 - 99,999 Writer B 100k - 199k Writer C 200k - 299k Writer D 300k - 399k Mapping store writes do not contend
The right thing to say is not a brand name. It is the contention shape: one allocator versus writers owning their own safe space.
Weak
We can use UUIDs or Snowflake.
Strong
A central allocator is fine at modest scale, but if it becomes hot, I would hand writers pre-claimed ranges so the write path does not coordinate for every request.
Mini case study

A celebrity shares one short link. It now gets millions of clicks.

This is the clean pressure test for the design. The correct instinct is cache and async separation, not a dramatic re-architecture.

millions of readers Redirect service stateless and scalable Cache code = x7Ka9p absorbs the heat Mapping store cold for hot codes Analytics queue click event
When the spike arrives, the cache absorbs the reads, the redirect service scales horizontally, and analytics stays off the user path.

What breaks first

  • Repeated redirect lookups for the same short code.
  • Repeated writes to analytics counters.

What helps first

  • Cache the mapping for that short code.
  • Keep the redirect service stateless and horizontally scalable.
  • Send analytics writes to a queue or buffered pipeline.

What should not happen

  • Every redirect hits the primary data store directly.
  • Analytics failures block redirects.

The lesson

  • The lookup path and analytics path should separate cleanly under spikes.
Demo conversation

How a strong exchange sounds.

Interviewer
What are the two most important paths here?
Candidate
The write path is short URL creation, and the read path is redirect lookup. The redirect path is hotter, so I want that path extremely thin and cache-friendly.
Interviewer
What is the hardest correctness problem?
Candidate
Unique code generation across many writers. If multiple servers create codes independently without coordination, collisions become a real risk.
Interviewer
How would you keep analytics from hurting redirects?
Candidate
I would acknowledge the redirect quickly, do the code lookup on the critical path, and move analytics onto an async side path so click tracking does not slow the user-facing response.
Worked example to solo answer

Fade the support before the real practice.

Do not jump straight from reading to a full answer. First see the shape, then complete part of it, then answer alone.

I do

Study the model move.

I would say: "The hot path is redirect, so I keep it thin: cache lookup, mapping store fallback, then async analytics."

We do

Complete the missing piece.

For custom aliases and expiration, mark which checks happen during create and which happen during redirect.

You do

Answer without notes.

Answer the practice prompt with two lanes and one side path.

Practice

Try it before you read the model answer.

Prompt
Design a URL shortener that supports custom aliases and expiration dates.
  • What stays in the baseline design?
  • What new checks does the write path need?
  • What does the main trade-off become?
Show a strong model answer
I would keep the baseline mapping store and fast redirect read path the same. The write path now needs alias validation, uniqueness checks for user-chosen codes, and expiration metadata stored with the mapping. On redirect, the service must also check whether the link has expired before returning the destination. The main trade-off is a richer product versus a more complicated write path and slightly more redirect logic.
Training loop

Make this chapter stick.

Before moving on, turn recognition into production. Close the model answer, answer from memory, then retry one small slice.

Recall

Say the chapter's core idea without looking. Then name one related idea from an earlier chapter.

Vary

Change one constraint in the practice prompt and answer again in half the time.

Score

Use the rubric to pick one dimension below 3, then retry only that dimension.

Memory hook
Generate safely. Lookup fast. Count later.
Recap

Three things to take into the room.

1

The redirect path is the product.

Optimize the read lane first. Everything else exists to protect it.

2

Uniqueness is a write-path question.

Talk about contention shape, not branded algorithm names.

3

Side work belongs off the critical path.

Analytics, abuse checks, and dashboards should be asynchronous unless the product promise says otherwise.

Reusable interview line
"The redirect path is the product, so I will keep it thin: cache in front, async analytics behind, and unique code generation handled where it does not fight the read lane."