System Design Diagram Example: A URL Shortener from Requirements to Diagram

A worked system design diagram for a URL shortener: requirements, back-of-the-envelope numbers, separate read and write paths, and a layout that shows the reasoning.

10/22/2026

System Design Diagram Example: A URL Shortener from Requirements to Diagram

In a system design interview or a design document, the diagram is where the reasoning becomes visible. A box labeled "cache" is easy to draw; showing why it is there, how much traffic it absorbs and what happens when it is cold is what makes the diagram worth reading.

This guide walks through a classic exercise, a URL shortener, from requirements to a finished system design diagram. The point is not the shortener itself but the method: requirements and numbers first, then the API and the data, then the boxes, with each decision written where people can see it.

Step 1: Requirements

Functional:

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

Non-functional:

  • Redirects must be fast and highly available; creating links can tolerate more latency.
  • The system is read-heavy: links are created once and clicked many times.
  • Short codes should not be easy to enumerate.

Step 2: Back-of-the-envelope numbers

Assume 100 million new links per month and 100 redirects per link created:

Quantity Estimate
Writes 100M / 2.6M seconds per month ≈ 40 per second on average
Reads 100 × 40 ≈ 4,000 redirects per second; plan for 10× peaks, 40,000 per second
Links after 5 years 100M × 12 × 5 = 6 billion
Storage 6 billion × ~500 bytes ≈ 3 TB, before replicas
Code length 7 characters of base62 give 62⁷ ≈ 3.5 trillion codes

The numbers already shape the design: reads dominate, so the read path gets a cache; 3 TB will not stay on one small database forever, so the data model must shard cleanly; and 7 characters leave plenty of room.

Step 3: API

POST /api/links
{ "url": "https://example.com/a/very/long/path", "alias": "launch", "expiresAt": "2027-01-01" }
→ 201 { "code": "launch", "shortUrl": "https://s.example/launch" }

GET /{code}
→ 302 Location: https://example.com/a/very/long/path

One decision deserves a line on the diagram: 301 or 302? A 301 is permanent, so browsers cache it and repeat visits never reach you. That saves traffic but loses click counts. A 302 sends every click through the redirect service, which is what analytics needs. This design uses 302.

Step 4: Data model and IDs

The core table is simple: code (primary key), long_url, owner_id, created_at, expires_at. Every read is a lookup by code, so either a key-value store or a relational database with a primary key works, and sharding by a hash of code spreads the load evenly.

Generating codes is the interesting part:

Approach Pros Cons
Counter + base62 No collisions Sequential codes are easy to enumerate; needs coordination
Random 7 characters Hard to guess, no coordination Must check for collisions on insert
Hash of the URL Same URL gets the same code Collisions on truncation; aliases need special handling

Here, the write API leases ranges of IDs from an ID range allocator, for example a million at a time, and scrambles each ID with a reversible permutation before base62 encoding, so codes are unique without a collision check and not sequential to an outsider.

Step 5: The diagram

Separate the paths that have different requirements. The write path is low volume and must be correct; the read path is high volume and must be fast; analytics can lag behind.

System design diagram of a URL shortener: writes go to a write API that leases IDs from an allocator and stores links; redirects read Redis first, then the links database, and send click events through Kafka to analytics.

11 components · 10 connections

Open in Archboard
Diagram contents
  • Users
  • Load balancer
  • ID range allocator
  • Write API
  • Redirect service
  • Cache: code → URL
  • Links DB (sharded by code)
  • click events
  • Analytics workers
  • Analytics store
  • HTTPS
  • POST · 40/s
  • GET · 4k/s, peak 40k/s
  • lease ID range
  • INSERT link
  • GET code
  • on cache miss
  • click event
  • consume
  • counts
The URL shortener from this guide: a write path through an ID allocator, a read path served from a Redis cache, asynchronous click analytics, and the estimates that drove the design.

How to read it:

  • Write path (top). The load balancer routes POST /api/links to the write API, which takes an ID from its leased range, encodes it and writes the link to the database.
  • Read path (middle). GET /{code} goes to the redirect service, which checks Redis first. With a hot set that fits in memory, most redirects never touch the database. On a miss it reads the database and fills the cache.
  • Analytics (bottom). Every redirect emits a click event to Kafka, and analytics workers aggregate counts into the analytics store. The redirect never waits for analytics.

Draw it so the reasoning shows

  • Put numbers on the edges. 40/s on the write edge and 4k/s, peak 40k/s on the read edge explain the cache better than any label.
  • Write assumptions next to the boxes. "Cache hit ratio target 90%", "302 for analytics", "IDs leased in ranges of 1M".
  • Separate synchronous and asynchronous. Solid edges for the request path, dashed for click events.
  • Show what happens when something fails. If Redis is down, redirects fall back to the database at higher latency; write that on the diagram.
  • Keep the estimates on the canvas. A small table of numbers next to the diagram turns it into a design document.

Deep dives worth preparing

  • Caching. Hot links follow a long-tail distribution, so an LRU cache with a modest TTL covers most traffic. Invalidate on delete and expiry.
  • Database scaling. Read replicas help less here than the cache does; sharding by code keeps writes and storage growing evenly.
  • Expiry. Check expires_at on read and clean up in the background, instead of a giant delete job.
  • Abuse. Rate-limit link creation per user and check target URLs against malware lists.

Build it in Archboard

  1. Sign in with Google or GitHub and create a diagram.
  2. Add a Network pack Internet node for users and a Cloud pack Cloud LB for the load balancer.
  3. Add the write API, the redirect service, the ID allocator and the analytics workers as Container nodes from the C4 Model pack, with the language in the technology field.
  4. Add a Data pack Redis for the cache, Postgres for the links database, a Topic for click events and a Data Warehouse for analytics.
  5. Label edges with operations and rates, make the click events dashed, and put the estimates in a Core Markdown block.

The example uses 11 diagram nodes, including the Markdown block with the estimates, within the Free plan. For the general method behind any architecture diagram, see how to draw a software architecture diagram.

FAQ

How detailed should a system design diagram be in an interview? Enough to show the read and write paths, the data store, the cache and one asynchronous piece. Go deeper only where the interviewer asks.

SQL or NoSQL for the links table? Either works for a primary-key lookup. Pick based on how you plan to shard and what your team runs well, and write the reason on the diagram.

Should I draw a CDN? Only if you cache redirects at the edge. With 302 and click counting, edge caching is limited, so many designs leave it out.

Why not 301 everywhere? A 301 saves traffic but browsers stop asking you, so you lose click data and cannot change the target for repeat visitors.

Where do the numbers go? On the canvas, next to the diagram, so anyone reviewing the design can check the assumptions behind the boxes.

Start free — one seat, no credit card.

Related posts

← Back to blog

Open a canvas in a minute

Sign in with Google or GitHub. Free for a single seat. Upgrade when the team joins.