Cheat SheetsSystem DesignReal-World Designs

Real-World Designs — Cheat Sheet

System Design · 6 topics. Download the PDF or the Instagram carousel and share it.

Cheat Sheet · AiCanCode.org
Real-World Designs
System Design6 topicsQuick revision reference
1

Design: URL Shortener

A URL shortener (like bit.ly) maps long URLs to short codes, stores the mapping in a database, and redirects users from the short URL to the original. Key challenges include unique ID generation, high-read throughput, and analytics.

  • Core: generate unique short code, store mapping, redirect with 301/302.
  • Base62 encoding of auto-increment ID is simplest — no collision, predictable length.
  • Read-heavy (100:1) — Redis cache with ~99% hit rate handles most redirects.
  • Analytics via async event streaming (Kafka) — never block the redirect path.
  • A 7-character base62 code supports 3.5 trillion URLs — more than enough for most systems.
Conceptual — URL shortener architecture
// URL Shortener architecture
//
//  Client: POST /api/shorten { url: "https://very-long-url.com/..." }
//    │
//    ▼
//  ┌──────────────────┐
//  │   API Service     │ → generate short code → store in DB
//  │   (stateless)     │ → return short.ly/abc123
//  └──────┬───────────┘
//         │
//  Client: GET short.ly/abc123
//    │
//    ▼
//  ┌──────────────────┐     ┌──────────┐
//  │  Redirect Service │────►│  Cache    │ (Redis: shortCode → longURL)
//  │  (stateless)      │     │  (L1)     │
//  └──────────────────┘     └──────┬───┘
//                                  │ cache miss
//                                  ▼
//                           ┌──────────┐
//                           │    DB     │ (DynamoDB / PostgreSQL)
//                           └──────────┘
//
//  Response: HTTP 301 Location: https://very-long-url.com/...
2

Design: Chat System

A real-time chat system (WhatsApp, Slack) requires persistent WebSocket connections, message ordering, delivery guarantees (sent/delivered/read), offline message storage, and group messaging.

  • WebSocket connections for real-time bidirectional communication; push notifications for offline users.
  • Message store (Cassandra) partitioned by conversation_id — write-optimised, time-ordered.
  • Presence service (Redis) tracks online/offline status via heartbeats.
  • Cross-server message routing via Redis pub-sub or internal message bus.
  • Delivery receipts (sent/delivered/read) require acknowledgement from client devices.
Conceptual — chat system architecture
// Chat system architecture
//
//  User A (sender)                          User B (receiver)
//    │ WebSocket                               ▲ WebSocket
//    ▼                                         │
// ┌─────────────┐                        ┌─────────────┐
// │ WS Gateway   │────────────────────────│ WS Gateway   │
// │ (stateful)   │                        │ (stateful)   │
// └──────┬──────┘                        └──────▲──────┘
//        │                                       │
//        ▼                                       │
// ┌─────────────┐    ┌──────────┐    ┌──────────────┐
// │ Chat Service │───►│ Message   │───►│ Message Fan- │
// │              │    │ Store     │    │ Out Service   │
// └──────┬──────┘    │(Cassandra)│    └──────┬───────┘
//        │           └──────────┘           │
//        ▼                                   ▼
// ┌─────────────┐                   ┌──────────────┐
// │ Presence Svc │                   │ Push Notif    │
// │ (Redis)      │                   │ (FCM / APNs)  │
// └─────────────┘                   └──────────────┘

// Message flow:
// 1. User A sends message via WebSocket
// 2. Chat service validates, assigns message_id + timestamp
// 3. Store in message DB
// 4. Check if User B is online (presence service)
//    Online: forward via WebSocket gateway
//    Offline: queue push notification
3

Design: Notification Service

A notification service delivers messages to users via multiple channels (push, email, SMS, in-app). It must handle high throughput, user preferences, rate limiting, and reliable delivery with retries.

  • Decouple notification requests from delivery using message queues — producers are not blocked.
  • Multi-channel delivery (push, email, SMS, in-app) based on user preferences per notification category.
  • Priority queues ensure critical notifications (OTP, security) are never delayed by marketing.
  • Rate limiting prevents notification fatigue — configurable per channel and per user.
  • Retry with backoff + DLQ for reliable delivery; idempotency keys prevent duplicate sends.
Conceptual — notification service architecture
// Notification service architecture
//
// Order Service ─┐
// Auth Service  ──┤  Notification Request
// Payment Svc  ──┤  (user_id, type, data)
//                 │
//                 ▼
//          ┌──────────────┐
//          │  Kafka Topic  │  (notification-requests)
//          └──────┬───────┘
//                 │
//                 ▼
//          ┌──────────────┐
//          │ Notification  │  1. Look up user preferences
//          │ Service        │  2. Render template
//          │               │  3. Route to channel queues
//          └──┬────┬───┬──┘
//             │    │   │
//             ▼    ▼   ▼
//          Push  Email  SMS     ← channel-specific queues
//          Queue  Queue  Queue
//             │    │   │
//             ▼    ▼   ▼
//          FCM/  Send-  Twilio  ← external providers
//          APNs  Grid
4

Design: News Feed

A news feed (Facebook, Twitter/X) aggregates posts from followed users and ranks them for display. The core trade-off is fan-out on write (pre-compute feeds) vs fan-out on read (compute at request time).

  • Fan-out on write: fast reads, expensive writes — good for users with few followers.
  • Fan-out on read: cheap writes, slower reads — good for celebrities with millions of followers.
  • Hybrid approach: fan-out on write for regular users, fan-out on read for celebrities.
  • Feed ranking considers recency, engagement, relationship strength, and content type.
  • Redis sorted sets are ideal for pre-computed feed caches — scored by timestamp or ranking score.
Conceptual + Redis — fan-out strategies
// Fan-out on write (push model)
// User posts → push to all followers' feed caches
//
// Alice (1000 followers) posts "Hello World"
// → Write to 1000 feed caches (one per follower)
// → Bob opens feed → read from pre-computed cache (fast!)
//
// Problem: Celebrity with 10M followers → 10M writes per post! 😱

// Fan-out on read (pull model)
// User opens feed → fetch posts from all followed users → merge + rank
//
// Bob follows 500 users → opens feed
// → Query 500 users' recent posts → merge → rank → return
// → Slow if following many users

// Hybrid (Twitter/X approach)
// Regular users (< 10K followers): fan-out on write
// Celebrities (> 10K followers): fan-out on read
//
// Bob's feed = pre-computed cache (regular follows)
//            + real-time merge (celebrity follows)

// Feed cache (Redis sorted set per user)
// Key: feed:bob
// Members: post_ids, scored by timestamp
ZADD feed:bob 1711700000 "post:123"
ZADD feed:bob 1711699000 "post:456"
ZREVRANGE feed:bob 0 19  // top 20 posts, newest first
5

Design: Distributed Cache

A distributed cache (Redis Cluster, Memcached) spreads cached data across multiple nodes using consistent hashing. It must handle cache invalidation, eviction, replication, and the thundering herd problem.

  • Distributed cache partitions data across nodes using consistent hashing (Redis: 16384 hash slots).
  • Each shard is replicated for fault tolerance — automatic failover if master dies.
  • Thundering herd: use mutex locks or staggered TTLs to prevent stampede on popular key expiry.
  • Hot keys: replicate across nodes, use local L1 cache, or split into multiple sub-keys.
  • Eviction (LRU) + TTL together bound both memory usage and staleness.
Conceptual — Redis Cluster with sharding and replication
// Redis Cluster architecture
//
//  Application Instances
//    │  │  │
//    ▼  ▼  ▼
// ┌──────────────────────────────────────────┐
// │           Redis Cluster                    │
// │                                            │
// │  Shard 1         Shard 2         Shard 3   │
// │  slots 0-5460    slots 5461-10922 slots 10923-16383
// │  ┌────────┐     ┌────────┐     ┌────────┐ │
// │  │Master 1│     │Master 2│     │Master 3│ │
// │  └───┬────┘     └───┬────┘     └───┬────┘ │
// │      │              │              │       │
// │  ┌───▼────┐     ┌───▼────┐     ┌───▼────┐ │
// │  │Replica 1│     │Replica 2│     │Replica 3│ │
// │  └────────┘     └────────┘     └────────┘ │
// └──────────────────────────────────────────┘
//
// Key routing: slot = CRC16(key) % 16384
// Client knows slot→node mapping → direct connection
// If wrong node: MOVED redirect → client updates mapping
6

Design: Rate Limiter

A rate limiter service enforces request quotas per client using algorithms like token bucket or sliding window. It must be distributed (shared state via Redis), low-latency, and support tiered limits.

  • Rate limiter sits at the API gateway — checks Redis counters on every request.
  • Token bucket allows bursts; sliding window is more accurate but uses more memory.
  • Redis Lua scripts provide atomic check-and-increment for distributed rate limiting.
  • Support tiered limits per client plan (free, pro, enterprise) with configurable rules.
  • Return 429 with X-RateLimit-* and Retry-After headers for graceful client back-off.
Conceptual + JSON — rate limiter architecture and rules
// Rate limiter architecture
//
//  Client Request
//    │
//    ▼
// ┌──────────────────┐
// │  API Gateway       │
// │  ┌──────────────┐ │     ┌──────────────┐
// │  │ Rate Limiter  │◄────►│    Redis      │ (shared counters)
// │  │ Middleware     │ │     └──────────────┘
// │  └──────┬───────┘ │     ┌──────────────┐
// │         │         │     │ Rules Config  │ (rate limit rules)
// │         │ allowed? │     └──────────────┘
// │         ▼         │
// │  ┌──────────────┐ │
// │  │ Route to      │ │
// │  │ Backend Svc   │ │
// │  └──────────────┘ │
// └──────────────────┘

// Rate limiting rules (config)
{
  "rules": [
    {
      "endpoint": "/api/v1/orders",
      "method": "POST",
      "limits": {
        "free":       { "requests": 10,   "window": "1m" },
        "pro":        { "requests": 100,  "window": "1m" },
        "enterprise": { "requests": 1000, "window": "1m" }
      }
    },
    {
      "endpoint": "/api/v1/auth/login",
      "limits": { "default": { "requests": 5, "window": "1m" } }
    }
  ]
}
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/system-design