Skip to content
System Design Fundamentals

Lesson 12 of 12 · 24 min

x
12/12

Lesson position in the course — not completion. Use Mark Complete to track finished lessons (saved in this browser).

Case Study: Design a URL Shortener

URL shorteners receive a long URL, generate a short code, and redirect users. It sounds trivial but the production version touches almost every system design concept: write throughput, read throughput 100× higher, caching, database choice, collision handling, and analytics at scale.

Scale estimate: 100M URLs shortened per day = ~1,200 writes/sec. Redirects at 10:1 read ratio = 12,000 reads/sec, each must complete under 10ms. Design: Postgres handles writes. A Redis cache serves the top 20% of codes that account for 80% of traffic (Pareto distribution). The short code is base62 of a database counter — no hash collisions. Analytics events go to Kafka and are processed asynchronously, never in the redirect critical path.

Before
Naive — everything synchronous in the redirect
1async function redirect(shortCode: string) {2  const url = await db.query(           // 20ms3    'SELECT long_url FROM urls WHERE code = $1',4    [shortCode]5  );6  await analytics.record(shortCode);    // 50ms — blocks!7  await db.query(                       // 10ms8    'UPDATE urls SET clicks = clicks + 1 ...',9    [shortCode]10  );11  return redirect(url.long_url);        // total: ~80ms12}
After
Production — fast path + async analytics
1async function redirect(shortCode: string) {2  // 1. Redis first — sub-ms to a few ms on hit when local/same-AZ (measure; 80% Pareto illustration)3  const cached = await redis.get(`url:${shortCode}`);4  if (cached) {5    kafka.publish('redirect', { shortCode }); // fire & forget6    return redirect(cached);  // total: ~1ms7  }8 9  // 2. Cache miss — read DB, then cache it10  const { long_url } = await db.query(/* sketch: SELECT long_url ... */); // tens of ms typical on warm DB — measure11  await redis.setex(`url:${shortCode}`, 86400, long_url);12  kafka.publish('redirect', { shortCode });  // fire & forget13  return redirect(long_url); // total: ~25ms on miss14}15// Kafka consumer batch-updates click counts — off critical path

Check your understanding

  • Why cache redirects aggressively?Show answer

    Answer

    Reads dominate writes; hot codes can be served from Redis/CDN without hitting the DB every time.
  • Where should click analytics run?Show answer

    Answer

    Off the critical path — e.g. publish to a queue/stream and update counts asynchronously.
  • Why prefer a counter→base62 code over hashing the URL?Show answer

    Answer

    Avoids collision handling complexity for the short-code space when a monotonic id is available.
Previous

Progress is saved in this browser.

Finish Course