Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

System Design Framework: Universal Approach

🎯 The 4-Step Framework

Use this framework for any system design question:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            SYSTEM DESIGN FRAMEWORK                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                         β”‚
β”‚  STEP 1: REQUIREMENTS (5 min)                           β”‚
β”‚  β”œβ”€β”€ Functional requirements (what it does)             β”‚
β”‚  β”œβ”€β”€ Non-functional requirements (how it performs)      β”‚
β”‚  β”œβ”€β”€ Constraints & assumptions                          β”‚
β”‚  └── Capacity estimation                                β”‚
β”‚                                                         β”‚
β”‚  STEP 2: HIGH-LEVEL DESIGN (10 min)                     β”‚
β”‚  β”œβ”€β”€ Core components                                    β”‚
β”‚  β”œβ”€β”€ Data flow                                          β”‚
β”‚  β”œβ”€β”€ API design                                         β”‚
β”‚  └── Database schema (high-level)                       β”‚
β”‚                                                         β”‚
β”‚  STEP 3: DEEP DIVE (20 min)                             β”‚
β”‚  β”œβ”€β”€ Detailed component design                          β”‚
β”‚  β”œβ”€β”€ Database schema (detailed)                         β”‚
β”‚  β”œβ”€β”€ Scaling strategy                                   β”‚
β”‚  β”œβ”€β”€ Bottleneck identification & resolution             β”‚
β”‚  └── Monitoring & reliability                           β”‚
β”‚                                                         β”‚
β”‚  STEP 4: TRADE-OFFS & WRAP-UP (10 min)                  β”‚
β”‚  β”œβ”€β”€ Pros/cons of key decisions                         β”‚
β”‚  β”œβ”€β”€ Alternative approaches                             β”‚
β”‚  β”œβ”€β”€ Future improvements                                β”‚
β”‚  └── Summary                                            β”‚
β”‚                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Step 1: Requirements (5 minutes)

Functional Requirements

Ask: β€œWhat does the system need to do?”

Example (URL Shortener):
βœ… Users can create short URLs from long URLs
βœ… Users are redirected when visiting short URLs
βœ… Users can customize short URL aliases
βœ… Links expire after a configurable time
βœ… Users can view analytics (click counts)

❌ Out of scope:
- User authentication (assume handled elsewhere)
- Payment processing
- Mobile app design

Tip: Start with 3-5 core features. Ask the interviewer which ones to focus on.

Non-Functional Requirements

Ask: β€œHow should the system perform?”

Availability:    99.99% uptime (52 min downtime/year)
Latency:         < 100ms for redirects
Throughput:      100M URLs created/day
Consistency:     Eventual consistency OK for analytics
Durability:      URLs should not be lost
Scalability:     Handle 10x traffic spikes

Capacity Estimation

Traffic:
- 100M URLs created/day = ~1,160 URLs/sec
- 10:1 read:write ratio = ~11,600 reads/sec
- Peak: 2x average = ~2,320 writes/sec, ~23,200 reads/sec

Storage:
- Each URL record: ~500 bytes (long URL + short code + metadata)
- 100M/day Γ— 365 days Γ— 5 years = 182.5B records
- 182.5B Γ— 500 bytes = ~91 TB

Bandwidth:
- Write: 1,160 Γ— 500 bytes = ~580 KB/s
- Read: 11,600 Γ— 500 bytes = ~5.8 MB/s

Step 2: High-Level Design (10 minutes)

Draw the Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  │────→│ Load Balancer│────→│  API Servers  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                              β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚                         β”‚                β”‚
              β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
              β”‚   Cache    β”‚          β”‚   Database   β”‚  β”‚  Queue   β”‚
              β”‚  (Redis)   β”‚          β”‚ (PostgreSQL) β”‚  β”‚ (Kafka)  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

API Design

POST /api/v1/urls
  Request:  { "long_url": "https://...", "custom_alias": "my-link", "expires_at": "..." }
  Response: { "short_url": "https://short.ly/abc123", "created_at": "..." }

GET /{short_code}
  Response: 301 Redirect to long URL

GET /api/v1/urls/{short_code}/analytics
  Response: { "total_clicks": 1234, "clicks_by_date": {...}, "referrers": {...} }

DELETE /api/v1/urls/{short_code}
  Response: { "status": "deleted" }

Database Schema (High-Level)

-- Core table
urls (
    id            BIGINT PRIMARY KEY,
    short_code    VARCHAR(10) UNIQUE NOT NULL,
    long_url      TEXT NOT NULL,
    user_id       BIGINT,
    created_at    TIMESTAMP,
    expires_at    TIMESTAMP,
    click_count   BIGINT DEFAULT 0
)

-- Analytics table (append-only)
click_events (
    id            BIGINT PRIMARY KEY,
    short_code    VARCHAR(10),
    clicked_at    TIMESTAMP,
    ip_address    VARCHAR(45),
    user_agent    TEXT,
    referrer      TEXT
)

Step 3: Deep Dive (20 minutes)

Pick 2-3 Components to Deep Dive

Always ask: β€œWhich component would you like me to dive deeper into?”

Common deep-dive topics:

  1. Data Storage β€” Sharding, replication, indexing
  2. Caching β€” Strategy, invalidation, consistency
  3. Scaling β€” Horizontal scaling, load balancing
  4. Reliability β€” Failover, redundancy, monitoring

Deep Dive: Caching Strategy

Cache-Aside Pattern (most common):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  │────────→│   App    │────────→│ Database β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚  Server  β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
                          β”‚
                     β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
                     β”‚  Cache   β”‚
                     β”‚ (Redis)  β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Read Path:
1. Check cache β†’ Hit? Return cached data
2. Cache miss β†’ Query database
3. Store result in cache β†’ Return data

Write Path:
1. Write to database
2. Invalidate cache (delete key)
3. Next read will fetch fresh data from DB

Cache Eviction:
- LRU (Least Recently Used) β€” default for most cases
- TTL (Time To Live) β€” for time-sensitive data

Deep Dive: Database Sharding

Sharding by Short Code (Hash-based):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Hash Function                 β”‚
β”‚     shard_id = hash(short_code) % N     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         β”‚         β”‚         β”‚
β”Œβ”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”
β”‚Shard0β”‚ β”‚Shard1β”‚ β”‚Shard2β”‚ β”‚Shard3β”‚
β”‚ a-f  β”‚ β”‚ g-l  β”‚ β”‚ m-r  β”‚ β”‚ s-z  β”‚
β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜

Pros: Even distribution, simple routing
Cons: Range queries hard, resharding complex

Deep Dive: Scaling

Horizontal Scaling:
β”œβ”€β”€ Stateless API servers behind load balancer
β”œβ”€β”€ Database read replicas for read-heavy workloads
β”œβ”€β”€ Cache cluster (Redis Cluster)
└── Message queue for async processing

Load Balancing:
β”œβ”€β”€ L4 (TCP) β€” Fast, simple
β”œβ”€β”€ L7 (HTTP) β€” Content-aware routing
β”œβ”€β”€ Algorithms: Round Robin, Least Connections, IP Hash
└── Health checks every 5-10 seconds

Step 4: Trade-offs & Wrap-up (10 minutes)

Discuss Key Trade-offs

"I chose [Decision A] over [Decision B] because:

Decision: SQL vs NoSQL
β”œβ”€β”€ SQL chosen for: ACID compliance, complex queries
β”œβ”€β”€ Trade-off: Harder to scale horizontally
└── Mitigation: Read replicas, connection pooling

Decision: Cache-aside vs Write-through
β”œβ”€β”€ Cache-aside chosen for: Simpler, better for read-heavy
β”œβ”€β”€ Trade-off: Possible stale data
└── Mitigation: Short TTL, cache invalidation on write

Decision: Synchronous vs Async processing
β”œβ”€β”€ Async chosen for: Click analytics
β”œβ”€β”€ Trade-off: Eventual consistency
└── Acceptable: Analytics don't need real-time accuracy"

Mention Future Improvements

"If I had more time, I would consider:
1. Geographic distribution with multi-region deployment
2. Rate limiting to prevent abuse
3. Analytics with real-time streaming (Kafka + Flink)
4. A/B testing framework for URL aliases
5. Machine learning for spam detection"

πŸ“‹ System Design Checklist

Use this checklist to ensure you cover everything:

Requirements:
β–‘ Functional requirements defined
β–‘ Non-functional requirements quantified
β–‘ Capacity estimated (traffic, storage, bandwidth)
β–‘ Out of scope items listed

High-Level Design:
β–‘ Core components identified
β–‘ Data flow diagram drawn
β–‘ API endpoints designed
β–‘ Database schema outlined

Deep Dive:
β–‘ Database design (schema, indexing, sharding)
β–‘ Caching strategy (what to cache, TTL, invalidation)
β–‘ Scaling approach (horizontal, vertical, auto-scaling)
β–‘ Reliability (replication, failover, monitoring)
β–‘ Security (authentication, encryption, rate limiting)

Trade-offs:
β–‘ Key decisions justified
β–‘ Alternatives discussed
β–‘ Bottlenecks identified and addressed
β–‘ Future improvements mentioned

🎯 Common Mistakes to Avoid

  1. Jumping to solution without understanding requirements
  2. Over-engineering β€” Don’t design for Google scale if it’s a startup
  3. Ignoring non-functional requirements β€” Availability and latency matter
  4. Not drawing diagrams β€” Visual communication is essential
  5. Staying too abstract β€” Dive into specifics when asked
  6. Not discussing trade-offs β€” Every decision has pros and cons
  7. Forgetting operational concerns β€” Monitoring, alerting, deployment

πŸ”— Cross-References