Guide

A URL shortener turns a long link into a short code, such as sho.rt/x7Kp2Qa, and sends anyone who opens that code to the long link. It is the standard interview warm-up. The product is small, but the design still covers estimates, unique IDs, a read-heavy cache and an async analytics path.

The key idea is asymmetry. Redirects happen about 100 times as often as links are created. So the redirect path gets a strict latency budget, and everything else can be slower.

Requirements

Functional

  • Create a short link for a long URL, with an optional custom alias and expiry.
  • Redirect a short code to its long URL.
  • Count clicks per link.

Non-functional

  • Redirects: p99 under about 50 ms in one region, with very high availability.
  • Codes must be unique.
  • Links live for years, 5 or more by default.
  • Creates can take hundreds of milliseconds.

The numbers

Assume 100 million new URLs per month and a 100:1 read-to-write ratio.

Seconds per month ≈ 2.6 million      (30 days × 86,400 s)
Writes (avg):   100M / 2.6M          ≈ 40 creates/s
Writes (peak):  40 × 3               ≈ 120 creates/s
Reads (avg):    40 × 100             ≈ 4,000 redirects/s
Reads (peak):   4,000 × 3            ≈ 12,000 redirects/s
Links (5 years): 100M × 12 × 5       = 6 billion
Storage:         6B × ~500 B         ≈ 3 TB

Creates at about 120 per second need no special write pipeline. Redirects at about 12,000 per second need horizontal scale and a cache.

Design at a glance

The create path leases or encodes a code, inserts the row and returns the short URL. The redirect path checks the cache, falls back to the database on a miss, emits a click event and returns the redirect. The click event is sent after the redirect decision, so analytics never blocks the user.

Concepts in this topic

StepConceptWhat it answers
1Redirect status codesDoes the browser call you again on the next click?
2Short code generationHow do you mint unique codes at high volume?
3Click counting off the hot pathHow do you count clicks without slowing redirects?

API and data model

HTTP
POST /api/v1/links
Idempotency-Key: …
{ "url": "https://example.com/a/very/long/path", "alias": null, "expiresAt": null }
→ 201 { "code": "x7Kp2Qa", "shortUrl": "https://sho.rt/x7Kp2Qa" }

GET /x7Kp2Qa
→ 302 Location: https://example.com/a/very/long/path

Every redirect is a primary-key lookup on code. Keep the links table as the mapping source of truth, and keep click totals somewhere else.

SQL
CREATE TABLE links (
  code       varchar(10) PRIMARY KEY,
  long_url   text        NOT NULL,
  owner_id   bigint,
  created_at timestamptz NOT NULL DEFAULT now(),
  expires_at timestamptz,
  is_active  boolean     NOT NULL DEFAULT true
);

Key-value stores partitioned by hash(code) fit this access pattern well. Codes from a counter or hash look random enough that hash sharding spreads the load.

Caching

Use cache-aside on code → {long_url, expires_at, is_active}, with a TTL of hours plus jitter. On create or disable, delete the key instead of overwriting it. A viral code can cause a stampede when its key expires, so guard it with single-flight or early refresh (see cache stampede).

Failure modes

FailureEffectMitigation
Redis downSlower redirects, more database loadFall back to the database; add read replicas
Database primary downCreates failRedirects keep working from the cache and replicas
Queue downAnalytics lagDrop the event with a metric; never block the 302
Viral single codeOne cache node or shard overloadedReplicate hot keys, use a CDN, coalesce requests

Common mistakes

  • Counting clicks on the links row. Every redirect then becomes a write to your busiest table.
  • Choosing 301 for a product that sells analytics. Browsers may stop calling you at all.
  • Tying redirect success to analytics. If the analytics queue is slow, redirects should still work.

Key takeaways

  • Redirects dominate, so design the read path first: cache, scale out, optionally use a CDN.
  • Seven base62 characters cover billions of links with room to spare.
  • Use 302 or 307 when you need click counts or expiry.
  • Send click events asynchronously and never let them block a redirect.

Further learning

Alex Xu's ByteByteGo material walks through the same URL-shortener design with clear diagrams for key generation and the redirect path.

ByteByteGo blog (Alex Xu)Explain complex systems with simple terms, from the authors of the best-selling system design book series. Join over 1,000,000 friendly readers. Click to read ByteByteGo Newsletter, a Substack publication.blog.bytebytego.com The System Design PrimerLearn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. - donnemartin/system-design-primerGitHub

A concise walkthrough of the four-step interview framework, useful before you practice this case.

System Design Interview: A Step-By-Step GuideByteByteGo