45 min read Real-World Case Study Part 4 · Lesson 12 (12 / 14)
Course 11: Part 4 — Production Hardening, Blueprints & Framework

Lesson 11.12 — Designing a Real-World System: How to Design a Scalable URL Shortener

Bringing every building block together—Load Balancer, Caching, Replication, Sharding, Message Queue, and Observability—to engineer a complete, fault-tolerant, high-throughput system from scratch.

What You Will Learn

Complete End-to-End Workflow: From ambiguous requirements to rigorous back-of-the-envelope estimations.
Unique Short Code & Collision Elimination: Base62 encoding, counter IDs vs hashing, and Key Generation Service (KGS).
Redirection Optimization: HTTP 301 vs 302 trade-offs and sub-millisecond Redis Cache-Aside lookups.
Asynchronous Analytics Decoupling: Keeping the critical redirect path fast using Kafka and background workers.

1. All Concepts Together: Entering Real-World Architecture

In previous lessons, we studied the foundational building blocks of system design in isolation:

  • How a Load Balancer evenly spreads requests across a fleet of servers.
  • How Databases scale using Replication, Partitioning, and Sharding.
  • Why Caching is indispensable for relieving database load and dropping response latencies to single-digit milliseconds.
  • How Message Queues & Workers offload heavy background tasks to preserve fast user responses.
  • How Distributed Systems & CAP Theorem keep clusters coherent across unavoidable network partitions.
  • The practical trade-offs between Monoliths and Microservices.
  • How Cloud, Docker & CI/CD automate deployments and eliminate downtime.
  • Why Reliability, Security & Observability keep production systems protected, resilient, and transparent.

Until now, we examined each concept inside its own room. But in the real world, a software architect doesn't design "just a cache" or "just a load balancer." They build a living, breathing system where every component collaborates like precision clockwork.

Today, we put it all together. For the first time, we will assemble all these building blocks to design a classic high-scale system: A Scalable URL Shortener (such as TinyURL or Bitly).

2. What is a URL Shortener and Why is it Needed?

Modern web applications frequently generate long, cumbersome URLs containing nested paths, affiliate IDs, and marketing campaign parameters:

https://www.example.com/products/category/electronics/product/12345?utm_source=facebook&utm_medium=cpc&utm_campaign=summer_sale_2026&affiliate_id=987654

Sending this via SMS wastes character budgets (exceeding the standard 160-character limit), looks cluttered on social media feeds, and is impossible to print cleanly on billboards or brochures. A URL shortener generates a concise, elegant alias:

https://short.example/aB91x

When a user visits this shortened URL, our system instantaneously resolves the mapping and redirects the client's browser to the destination address.

Our Mission Today

How do we design a URL shortening system capable of serving billions of clicks with sub-10ms response latencies, zero collisions, and continuous high availability?

3. Deconstructing the Problem: The Two Core Operations

The first rule of system design is to distill complexity down to fundamental core operations:

Operation 1: Short Code Creation
Input: Long URL
↓ (System Logic)
Output: Unique Short Code Generated

Generate a deterministic 6-7 character unique token and persist the mapping in the data tier.

Operation 2: Redirection
Input: Short URL Access
↓ (Mapping Lookup)
Output: HTTP Redirect to Original URL

Lookup the original URL from memory/disk and redirect the client with minimal network latency.

4. Steps 1 & 2 — Functional & Non-Functional Requirements

Functional Requirements

  1. URL Shortening: Given a long URL, return an ultra-short alias (e.g. https://short.example/aB91x).
  2. Redirection: Visiting the short URL instantly redirects the client to the original long URL.
  3. Custom Alias (Optional): Users can request vanity aliases (e.g. short.example/salim).
  4. Expiration (Optional): Users can set link lifetimes (e.g. 7 or 30 days). Expired links return 404 Not Found.
  5. Analytics (Commercial requirement): Track click count, geographical location, referrer, and user-agent.

Non-Functional Requirements

  • High Availability (99.99%): Redirection must never drop; links printed in newspapers or marketing emails cannot fail.
  • Ultra-Low Latency: Redirection response must complete in < 10ms so users perceive immediate navigation.
  • Deterministic Uniqueness: Zero collisions—two different URLs must never receive the same active short code.
  • Scalability: The system must handle viral link traffic spikes effortlessly without database degradation.
Critical Insight: An Extreme Read-Heavy Workload

A short URL is created once (Write = 1). But that link is clicked thousands, millions, or billions of times (Read = 1,000,000+). Our system exhibits a severe Read:Write ratio of 100:1 to 1000:1. This primary characteristic dictates our caching, replication, and data tier architecture.

5. Steps 3 & 4 — API Design & Initial Architecture

Our service exposes two primary REST endpoints:

POST /api/v1/urls

Create a new shortened URL:

// Request Body
{
  "url": "https://example.com/very/long/url/for/summer-sale",
  "custom_alias": "summer26",  // Optional
  "expires_in_days": 30         // Optional
}

// Response (201 Created)
{
  "short_url": "https://short.example/summer26",
  "short_code": "summer26",
  "original_url": "https://example.com/very/long/url/for/summer-sale",
  "created_at": "2026-09-25T16:00:00Z",
  "expires_at": "2026-10-25T16:00:00Z"
}
GET /:short_code

Redirect request:

// Request: GET /aB91x

// HTTP Response Headers:
HTTP/1.1 302 Found
Location: https://example.com/very/long/url/for/summer-sale

6. Steps 5 & 6 — Database Schema & Unique Short Code Generation

Our relational schema requires a lean, index-optimized table:

CREATE TABLE urls (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    short_code VARCHAR(16) NOT NULL UNIQUE,
    original_url TEXT NOT NULL,
    user_id BIGINT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP NULL,
    INDEX idx_short_code (short_code)
);

The Algorithmic Challenge: Generating Unique Short Codes

We want compact codes like aB91x (6 to 7 characters). How do we mathematically guarantee zero collisions across billions of records?

Approach A: Base62 Encoding (The Standard Industry Solution)

Standard human numbers use Base10 (0-9). Hexadecimal uses Base16 (0-9, a-f). For clean, URL-safe strings, Base62 is the gold standard:

  • Digits: 0-9 (10 characters)
  • Lowercase letters: a-z (26 characters)
  • Uppercase letters: A-Z (26 characters)
  • Total Alphabet Size = 10 + 26 + 26 = 62 characters!
Base62 Combinatorial Power
6-Character Code ($62^6$): 56.8 Billion Unique URLs (56,800,235,584 distinct mappings)
7-Character Code ($62^7$): 3.52 Trillion Unique URLs (3,521,614,606,208 distinct mappings)

Using just 7 characters provides enough unique identifiers to shorten billions of links every year for centuries without repetition.

How it works: Take a sequential database auto-increment ID (e.g. 125). Divide repeatedly by 62 and collect the remainders to form the Base62 characters:

Database Auto-Increment ID (e.g. 125)
  ↓
Divide by 62: Quotient 2, Remainder 1  → '1'
Divide by 62: Quotient 0, Remainder 2  → '2'
  ↓
Base62 Short Code = "21" (Guaranteed 0% collisions!)

Approach B: Cryptographic Hash (MD5 / SHA-256) & Truncation

Hashing the URL with MD5 produces a 128-bit hex string (32 characters). Taking the first 7 characters yields compact codes, but introduces Hash Collisions: two distinct URLs may generate the identical first 7 characters! To resolve collisions, the service must query the database to verify uniqueness. If a collision occurs, it appends a salt/timestamp and re-hashes. At scale, these database lookups create latency spikes.

7. Steps 7 & 8 — Redirection Optimization & Caching

When redirecting user traffic, choosing between HTTP 301 and 302 represents an essential architectural trade-off:

HTTP 301 Moved Permanently

The client browser caches the redirect mapping permanently. Subsequent clicks bypass our backend servers completely.

Disadvantage: Zero click analytics can be recorded!
HTTP 302 Found (Temporary Redirect)

The browser contacts our backend on every click, allowing complete telemetry capture before issuing the redirect response.

Industry Standard: Bitly and TinyURL always use 302/307.

The Redis Cache-Aside Pattern

Because 302 redirects hit our infrastructure every time, querying the disk database on every click would overwhelm storage IOPS. We insert an in-memory Redis Cache:

User Click (GET /aB91x)
       |
       v
Application Server
       |
       v
+--------------+
| Redis Cache  |
+--------------+
       |
       +--- [CACHE HIT: ~2ms] ----> Original URL found!
       |                                   |
       |                                   v
       |                             Return HTTP 302 Redirect to User
       |
       +--- [CACHE MISS: ~35ms]
                   |
                   v
           Database Replica
                   |
                   v
            Original URL retrieved
                   |
                   v
         Cache backfilled in Redis (with TTL)
                   |
                   v
         Return HTTP 302 Redirect!

The 80/20 Pareto Rule: In practice, 20% of shortened URLs generate 80% of total click volume. Keeping this hot 20% in memory delivers sub-2ms lookups for 95%+ of incoming traffic.

8. Step 16 — Asynchronous Analytics Pipeline

Every click carries valuable telemetry: IP address, geolocation, referrer URL, and browser user-agent. However, executing synchronous database writes during the redirection request introduces intolerable latency.

Golden Architecture Rule: Never Block the Critical Path with Telemetry!

The user's primary demand is instant navigation. They do not care if click analytics take 5 seconds to process. Therefore, the redirect path must remain Synchronous (sub-5ms) while the analytics path is strictly Asynchronous (event queue).

User Request (GET /aB91x)
       |
       v
Application Server
       |
       +---> [Sync Path]  Redis Lookup ➔ 302 Redirect (User redirected in < 3ms!)
       |
       +---> [Async Path] Publish Event: Kafka / RabbitMQ Queue
                                |
                                v
                       Analytics Background Workers
                                |
                                v
                       Columnar OLAP Storage
                    (ClickHouse / TimescaleDB)

9. Complete URL Shortener System Architecture Blueprint

Here is the complete end-to-end production architecture:

                             GLOBAL CLIENTS
                                   |
                                   v
                        CDN / Cloudflare (WAF & DDoS)
                                   |
                                   v
                          Load Balancer (ALB)
                                   |
                +------------------+------------------+
                |                  |                  |
                v                  v                  v
           App Node 1         App Node 2         App Node 3
         (Stateless API)    (Stateless API)    (Stateless API)
                |                  |                  |
                +------------------+------------------+
                                   |
                 +-----------------+-----------------+
                 |                                   |
                 v                                   v
        [ In-Memory Cache ]                 [ Database Tier ]
          Redis Cluster                    Primary DB (Writes)
         (Sub-2ms Lookups)                           |
                                            Replication Sync
                                                     |
                                                     v
                                             Read Replicas (Reads)
                                                     |
                                            (On Cache Miss Only)

                 +-----------------------------------+
                 | Click Event Stream                |
                 v                                   v
       [ Message Queue / Kafka ]          [ Key Generation Service ]
                 |                               (KGS Fleet)
                 v
         Analytics Workers
                 |
                 v
      Columnar Storage (ClickHouse)
                 |
                 v
       Analytics Dashboard

      [ Observability: Prometheus Metrics + Grafana + OpenTelemetry ]

10. The Universal System Design Framework

The core value of this lesson is not just knowing how to build TinyURL. It is mastering the universal methodology for tackling any system design challenge:

// Universal System Design Step-by-Step Checklist:
1. Requirements Clarification: Define functional scope and non-functional constraints.
2. Capacity Estimations: Estimate throughput (RPS), storage growth, and cache RAM.
3. API Design: Define clear request/response contracts for core operations.
4. Data Model: Design the schema and justify Relational vs NoSQL selection.
5. High-Level Design: Connect core components into a functional baseline.
6. Bottleneck Analysis: Identify pressure points (Read-heavy, locks, network saturation).
7. Scale with Building Blocks: Introduce caching, load balancing, replicas, and queues.
8. Reliability & Trade-offs: Design for failure modes and articulate engineering compromises.

Interactive System Design Workbench

Test Base62 encoding, simulate cache redirection latencies, and calculate system capacity in real time

Live Simulator

Concept Check: Real-World Architecture Quiz

Verify your architectural reasoning with 3 scenario-based questions

Question 1

A marketing SaaS platform needs to track exact click counts, timestamps, and referrer sources for shortened links. Why should they configure HTTP 302 instead of HTTP 301?

Question 2

Why is Base62 encoding on an auto-increment or distributed ID preferred over hashing the URL with MD5 and truncating to the first 7 characters?

Question 3

During peak viral traffic of 30,000 requests/second, what occurs if click telemetry (IP, user-agent, timestamp) is written synchronously into the primary relational database before responding to the user?

Next Step · Part 4 · Lesson 13

Designing a Real-Time Chat System — How to Design a Scalable Messaging Service like WhatsApp

The URL shortener was comparatively straightforward. Next, we tackle a massive architectural challenge: millions of concurrent users chatting simultaneously, real-time message delivery, online/offline presence tracking, and managing persistent WebSocket connections!