Command Palette

Search for a command to run...

PHASE 12Advanced ~7 min· topic 1 of 39Level 1

System 12.1 — URL Shortener

In one line

The perfect first HLD: small data, global scale, one hot read path (redirect) and one rare write path (create).

0/39 · 0%

Think of it like this

Bit.ly. You paste a long, ugly link and get back a tiny one like 'sd.ly/x7K2'. Behind the scenes it's really just a giant lookup table: short code in, long URL out.

Key ideas

  1. 01

    Scale: ~100M URLs/day → ~1.2k writes/s, ~11k reads/s (avg), peak 5–10x.

  2. 02

    API: POST /api/shorten {url} → {shortId}; GET /{shortId} → 301/302 redirect (or JS). 301 = permanent, cached; 302 for analytics-aware redirects.

  3. 03

    Encoding: counter → Base62 (0-9a-zA-Z) gives 62^7 ≈ 3.5T ids in 7 chars — no md5 collisions to fight.

  4. 04

    Storage: RDBMS with (shortCode) unique PK; the write path is rare, reads are by key → index lookups trivial.

  5. 05

    Cache: hot codes in Redis (cache-aside) — redirect p99 goes from 5ms to ~2ms, DB relieved.

  6. 06

    Flow: POST → lock+counter (or ZK/Redis INCR) → generate code → insert → respond 201. GET → check cache → miss → lookup DB → redirect 301 + count event.

  7. 07

    Failures: cache DOWN → still works (falls to DB); DB writers locked per counter — make counter a Redis INCR to de-throttle.

  8. 08

    Extras: custom alias, expiry TTL, analytics events (async → Kafka), and remember 301 gets cached by browsers → analytics need 302 or client-side pixel.

Java / Spring map

  • →

    Spring Boot: @RestController + repository; Redis for cache + INCR counter; events published on redirect.

Code & diagrams

Base62Encoding.javajava

The only 'algorithm' the whole problem needs.

public final class Base62 {
  private static final String ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

  public static String encode(long n) {           // 0 → "0", 12345 → "3d7"
    StringBuilder sb = new StringBuilder();
    do { sb.append(ALPHABET.charAt((int) (n % 62))); n /= 62; } while (n > 0);
    return sb.reverse().toString();
  }
  public static long decode(String s) {
    long n = 0;
    for (char c : s.toCharArray()) n = n * 62 + ALPHABET.indexOf(c);
    return n;
  }
}
// Counter 1,250,000,000 → "1fEC7Ya" — 7 chars for ~1.2 billion urls.

Explain without notes

01

Why 301 breaks analytics + how a 302-and-pixel (or JS redirect) keeps counting.

Practice

01

Work the scale: 100M/day, 5-year retention → codes, DB size, cache size, QPS at peak.

Trade-offs

  • ↔

    Counter-based ids are guessable (SEO/hijack risk); random ids cost collision handling. Trade guessability vs complexity.

Run it in production

Completion checklist

  • I can present shortener across all 13 template sections in 25 minutes.

Back to phase