Real-World System Design — URL Shortener, Chat, Feed

লেসন ৪৫ / ৫০

1. URL Shortener (bit.ly)

Requirements

  • long URL → short URL (7 chars)
  • Redirect short → long
  • Custom alias, analytics, TTL

Capacity

100M new URLs/month = ~40/sec
Read:Write = 100:1 = 4000/sec reads
Storage: 500 bytes × 100M/mo × 60mo = 3TB

Design

POST /api/shorten → generate short code → save DB
GET /:code → lookup → 302 redirect

Short code generation:
  Option A: Base62 counter (a-z, A-Z, 0-9) = 62^7 = 3.5 trillion
  Option B: Hash(URL) + truncate + collision check
  Option C: Pre-generate pool, assign

Schema:
  urls(short_code PK, long_url, created_at, ttl, user_id)

Cache: Redis hot URLs (99% hit rate)
DB: sharded by short_code hash

Analytics

Async log clicks → Kafka → data warehouse → dashboard।

2. Chat App (WhatsApp)

Requirements

  • 1-1, group chat
  • Online status, typing, read receipt
  • Offline message
  • Media attachment

Architecture

Client ←→ WebSocket Gateway ←→ Chat Service
                                   ↓
                             [Message Queue]
                                   ↓
                         [Messages DB — Cassandra]
                                   ↓
                         [Presence — Redis]

Design Decisions

  • WebSocket — persistent connection for real-time
  • Cassandra — write-heavy, messages append
  • Redis — online users, ephemeral
  • User → which gateway? Consistent hashing
  • Offline: push notification (APNs, FCM)
  • Media: upload to S3, share URL
  • End-to-end encryption: Signal protocol

Schema

messages:
  conversation_id, message_id (UUID v1 time-ordered),
  sender_id, content, created_at
  -- Partition by conversation_id
  -- Sort by message_id DESC

3. Twitter Feed

Two Approaches

Pull (Fan-out on read)
User opens feed →
  Query: fetch tweets from all followed users
  Sort by time, return top N
✅ Simple write
❌ Slow read (celeb with 100M followers query heavy)
Push (Fan-out on write) ⭐
User tweets →
  For each follower → insert into their timeline cache
✅ Fast read (pre-computed)
❌ Write expensive (celeb 100M fan-out)
❌ Storage heavy
Hybrid
  • Normal user → push
  • Celebrity (>1M) → pull
  • Merge at read time

Storage

tweets(id, user_id, content, created_at, media_url)
  Partition by user_id
timeline_cache (Redis):
  ZADD timeline:user_id score=timestamp value=tweet_id
  ZREVRANGE timeline:123 0 50

4. Uber (Ride Hailing)

Challenges

  • Real-time driver location
  • Match rider ↔ nearest driver
  • Payment, surge pricing

Design

Driver app → location every 4s → Location Service → Redis Geohash

Rider request →
  Match Service: query geohash near pickup
  Filter available drivers
  Rank (ETA, rating)
  Offer to top driver
  Timeout → next driver

Technologies:
  WebSocket for real-time
  Kafka for event stream
  Cassandra for trip history
  Redis GEO commands (GEOADD, GEORADIUS)
  Elasticsearch for search

5. Rate Limiter

Algorithms

  • Fixed Window — counter reset per window (simple, burst issue)
  • Sliding Window — smooth (accurate)
  • Token Bucket ⭐ — tokens refill rate
  • Leaky Bucket — smooth output

Redis Implementation

# Token bucket
INCR rate:user:123
EXPIRE rate:user:123 60
-- if count > limit → 429

6. Notification System

Event source → Queue (Kafka) → Notification Service →
  Route by type:
    Push → FCM/APNs
    SMS → Twilio
    Email → SendGrid
    In-app → WebSocket

User preference DB: which channel for which event
Template engine: locale-aware
Batching: digest instead of per-event

Interview Approach ⭐

  1. Clarify requirements (functional + non-functional)
  2. Capacity estimate (users, QPS, storage)
  3. API design (endpoints)
  4. Data model (schema, DB choice)
  5. High-level architecture
  6. Deep dive (1-2 components)
  7. Bottlenecks + scaling
  8. Trade-offs discussion