Getting Started
What is System Design?
Defining the architecture, interfaces, and data of a system that meets specific requirements.
In short
Defining the architecture, interfaces, and data of a system that meets specific requirements.
1. Learning Objectives
In this lesson, you will learn the foundational principles of designing robust, high-performance, and scalable software architectures. By the end of this topic, you will be able to:
- Define System Design and explain its role in building large-scale applications.
- Distinguish between High-Level Design (HLD) and Low-Level Design (LLD) boundaries.
- Analyze major scalability and availability goals using architectural trade-offs.
- Apply a structured 4-step framework to approach open-ended system design interview questions.
2. Prerequisites
To get the most out of this lesson, you should have a basic understanding of:
- Client-Server Model: Understanding how web browsers or clients send HTTP requests and how servers return responses.
- Basic Programming Concepts: Familiarity with REST APIs, databases, and general software development lifecycles.
- Basic Networking: Knowledge of how devices are addressed using IP addresses.
3. Why This Topic Matters
Building a software application that works for 100 users is relatively straightforward. You can host your server, database, and files on a single machine, and it will run efficiently. However, when your user base grows to 100,000 or 10 million concurrent users, single-node architectures fail:
- Resource Saturation: A single server runs out of physical hardware limits (CPU cores, RAM limits, Disk I/O bandwidth).
- Single Point of Failure (SPOF): If the physical hardware crashes or loses power, the entire application goes offline.
- Data Bottlenecks: Multiple threads fighting to write to a single disk file create database contention and locking, causing request timeouts.
System Design provides the engineering blueprint to transition from single-node applications to reliable, distributed architectures. Distributed systems partition workloads across multiple servers, ensuring continuous availability, massive data capacity, and low latency.
4. Real-world Analogy
Think of system design as urban planning for a major metropolis rather than building a single house:
- Building a House (LLD): Focuses on the layout of a single building, placing rooms, electrical wiring, and plumbing pipes. This is equivalent to writing class hierarchies, functions, and patterns within a single app instance.
- Urban Planning (HLD): Focuses on designing high-speed multi-lane highways, traffic roundabouts (Load Balancers), power grids, and local zoning laws to prevent congestion. It places distribution centers (CDNs/Caches) close to residential neighborhoods so goods arrive faster.
- Metropolis growth: If you try to expand a village into a mega-city without planning, the roads will experience gridlock, utilities will collapse, and the city will grind to a halt. Similarly, software without system design collapses under real-world traffic load.
5. Core Concepts
Understanding system design requires mastership over several core terms and paradigms:
- Distributed Systems: A collection of independent computers (nodes) that communicate over a network and coordinate their actions to appear to end-users as a single, coherent system.
- High-Level Design (HLD): The conceptual architectural design outlining macro-components (load balancers, web servers, databases, caches, queues) and the protocols connecting them.
- Low-Level Design (LLD): The micro-design focusing on object relationships, object-oriented design patterns, concurrency controls, and code-level optimization inside a single node.
- Vertical Scaling (Scaling Up): Adding more hardware resources (more RAM, faster CPU, larger SSDs) to an existing single machine. It is simple but has a hard physical ceiling and introduces a Single Point of Failure (SPOF).
- Horizontal Scaling (Scaling Out): Adding more standard computers (nodes) to your resource pool. It has virtually no limit, but requires complex software coordination, networking, and data replication.
- Stateless Architecture: Designing application servers such that they do not store user sessions or application states in their local memory (RAM). Instead, state is externalized to a centralized datastore (like Redis or PostgreSQL). This allows any server in the cluster to handle any incoming request.
6. Visualization
The diagram below illustrates how client requests are received and routed in a standard multi-tier architecture, showing cache-aside retrieval and persistent database writes:
Architectural Boundaries (HLD vs LLD)
The following visual diagram maps the boundary between High-Level Design (how multiple distributed services communicate) and Low-Level Design (how objects are structured inside a single server):
7. How It Works
In a production system, a request completes a structured lifecycle across several tiers. Here is the step-by-step path:
- Domain Name Resolution: The client browser queries the Domain Name System (DNS) to resolve a human-readable URL (e.g.,
example.com) into a public IP address. - Static Asset Delivery: The browser requests static files (images, CSS, Javascript) from the nearest Content Delivery Network (CDN) edge node.
- Traffic Ingress: Dynamic API requests are routed to the system's public Load Balancer (LB) or API Gateway.
- Routing & Security: The LB performs TLS/SSL termination, applies rate limits, and routes the request to an available application server instance.
- Stateless Logic Processing: The application server processes the request. It fetches required data by checking the Cache Layer (Redis) first.
- Database Access: On a cache miss, the server queries the database (SQL/NoSQL) and populates the cache with the fetched record for future requests.
- Response Propagation: The application server wraps the response in a JSON/HTML format and returns it to the client through the load balancer.
8. Internal Architecture
A robust system design partitions components into discrete layers, following the principle of separation of concerns:
| Tier / Layer | Core Components | Primary Responsibilities | Failure Points |
|---|---|---|---|
| Edge Layer | DNS, CDN, Edge Proxies | Global routing, caching static assets close to users, DDoS mitigation. | Edge server outages, cache invalidation delays. |
| Routing / Gateway Layer | API Gateways, Load Balancers | SSL termination, request routing, rate limiting, authentication verification. | Mishandled SSL certificates, single point of failure (SPOF) if not clustered. |
| Compute Layer | Stateless App Servers, Microservices | Execution of business rules, microservice coordination, third-party integrations. | Out of memory (OOM) crashes, thread-pool starvation. |
| Cache Layer | Redis Clusters, Memcached | Low-latency read caching, session sharing, distributed locking. | Cache eviction cascades, stale data synchronization. |
| Storage / Data Layer | Relational (SQL) & NoSQL databases | Persistent write storage, ACID transaction compliance, historical records. | Database deadlocks, disk space exhaustion, replication lag. |
9. Request Lifecycle
Let us trace the complete lifecycle of a real-world request, for example, fetching a user profile via a mobile application client calling GET /api/v1/users/789:
- 1. DNS Routing & Gateway Handshake: The mobile app queries DNS, resolves the IP of the API Gateway, and sends a secure HTTP request with an authorization token. The gateway parses the token, verifies permissions, and maps the route to the internal
user-servicecluster. - 2. Load Balancer Routing: An internal software load balancer receives the request and routes it to
user-service-node-3using a Round-Robin algorithm. - 3. Cache Lookup (Cache-Aside pattern):
user-service-node-3intercepts the request and queries the Redis Cache cluster using the keyuser:789.- Cache Hit: Redis returns the cached JSON string. The server parses it and immediately returns the response (latency: ~2ms).
- Cache Miss: Redis returns null. The server proceeds to step 4 (latency: ~20ms+).
- 4. Database Read & Write-Back: On a cache miss, the server executes a query against the PostgreSQL database replica:
SELECT * FROM users WHERE id = 789;. Once the database returns the row, the server writes it to Redis with a Time To Live (TTL) of 3600 seconds, ensuring subsequent queries hit the cache. - 5. Serialization & HTTP Response: The server converts the database record into JSON, attaches HTTP response headers, and writes it back to the client connection.
10. Deep Dive
Structured Approach to System Design Problems
In engineering and interview settings, system design challenges are intentionally ambiguous. To solve them, you must apply a standard framework:
- Step 1: Understand the Requirements (Functional & Non-Functional): Clarify features (e.g., "users can upload photos") and scale targets (e.g., "10,000 photo uploads per second, 99.9% availability, max 200ms upload latency").
- Step 2: Core API & Data Schema Design: Define API signatures (REST endpoints or gRPC payloads) and design the database schema. Select SQL vs NoSQL based on data relationship complexity.
- Step 3: High-Level Architecture: Draw a block diagram showing clients, DNS, load balancers, web servers, databases, and caches. Walk through the happy-path request flow.
- Step 4: Scale the Design & Address Bottlenecks: Introduce database replication, caching, message queues to process slow tasks asynchronously, and rate limiting to defend against abuse.
Scaling Strategies: Horizontal vs. Vertical
When scaling systems, the physical limits of hardware dictate your scaling choices. Vertical scaling (upgrading to a larger server) is simple but limited by hardware cost bounds and the physical maximum of RAM/CPU cores. Horizontal scaling (adding more instances) provides infinite scale but requires partitioning, network routing protocols, and distributed consensus mechanisms.
11. Production Example
How real-world tech giants apply system design to handle billions of users:
- Netflix: Utilizes a stateless compute tier hosted on AWS. User recommendations and browsing are handled by thousands of independent microservices. Videos are served via a globally distributed custom CDN network called Open Connect, placing heavy media files close to local internet service provider (ISP) exchanges.
- Uber: Relies on geospatial indexing (using H3 hexagons) to partition coordinates. The matching algorithm coordinates ride requests and drivers asynchronously using Apache Kafka queues to absorb spikes, preventing database lock contention.
- Amazon: Implemented a completely decentralized microservices model where teams own services end-to-end. To ensure checkout availability even during system partitions, Amazon's shopping cart utilizes DynamoDB, trading strong consistency for high write availability (eventual consistency).
12. Advantages
Implementing structured system design yields major production benefits:
- Scalability: The system easily absorbs traffic growth by adding extra server nodes (horizontal scaling).
- High Availability: Redundant deployment across multiple data centers ensures the app stays online during natural disasters or power grid losses.
- Fault Isolation: Using decentralized microservices prevents a bug in a non-critical module (e.g., profile editing) from crashing the core flow (e.g., checkout).
- Resource Efficiency: Leveraging cache layers and CDNs reduces expensive database query costs and minimizes server compute overhead.
13. Limitations
Despite its benefits, complex system design introduces several engineering limitations:
- High Operational Complexity: Monitoring, deploying, and tracing requests across hundreds of distributed microservices requires advanced DevOps infrastructure (Kubernetes, distributed tracing).
- Consistency Management: Sharding and replicating data across geographic nodes leads to eventual consistency issues, requiring careful application logic to prevent stale data displays.
- Network Latency: Moving from single-process memory calls to remote network calls (REST/gRPC) introduces network latency overhead and packet transmission delays.
- Higher Initial Development Cost: Architecting for scale requires more upfront time, developer skills, and infrastructure costs compared to building a simple monolith.
14. Trade-offs
System design is not about finding a "perfect" solution; it is the art of choosing the right set of trade-offs for your specific constraints:
- Consistency vs. Availability (CAP Theorem): In the event of a network partition, you must decide whether to return an error to ensure all users see the exact same data (Consistency), or return stale/partial data to keep the system working (Availability).
- Latency vs. Throughput: You can optimize for latency (returning a single search query in <10ms via caching) or throughput (processing 100,000 transaction events in batches using a queue, which increases single-item processing time).
- Cost vs. Redundancy: Running active-active replication across three global regions ensures zero data loss and near-instant failover, but triples monthly cloud infrastructure bills.
15. Performance Considerations
To evaluate the efficiency of your architecture, monitor these key performance indicators:
- Response Latency: Focus on high percentiles (p95, p99) rather than averages. A p99 of 200ms means 1% of users wait longer than 200ms, which is critical at scale.
- Throughput (QPS/TPS): The maximum volume of queries or transactions processed per second before latency spikes.
- Serialization Overhead: JSON parsing is CPU-intensive. Replacing it with binary serialization protocols (e.g., Protocol Buffers or Avro) reduces network payload size and CPU usage.
- Database Connection Pools: Reuse database connections. Creating a new TCP connection handshake for every single API request degrades database CPU performance.
16. Failure Scenarios
In distributed systems, failures are inevitable. We must build fault-tolerant architectures:
- Single Point of Failure (SPOF):
Impact: If a single database instance fails, the entire application goes offline.
Mitigation: Configure primary-replica replication with automated failover detection (e.g., Sentinel or ZooKeeper). - Cascading Failures (System Overload):
Impact: Service A slows down, causing Service B to run out of connection threads, which crashes Service C.
Mitigation: Equip services with Circuit Breakers that immediately trip and fail fast when a dependency is down, preventing exhaustion of threads. - Cache Stampede:
Impact: A popular cache key (e.g., homepage banner) expires, causing 10,000 concurrent requests to hit the database at once, crash the database.
Mitigation: Implement mutual exclusion locking (using Redis locks) during cache refills, or use background threads to refresh cache keys before they expire.
17. Best Practices
Follow these core principles when building scalable systems:
- Decouple Services: Use asynchronous message queues (RabbitMQ, Kafka) to isolate independent processing steps, preventing tight coupling.
- Defend via Rate Limiting: Deploy rate limiters at the API gateway layer to prevent malicious scrapers or API bugs from overloading your compute nodes.
- Enforce Graceful Degradation: If a non-essential service (like user profile recommendations) fails, catch the error and return an empty recommendation list, allowing the user to complete checkout.
- Stateless Compute: Keep application nodes 100% stateless. Store session states in Redis or verify requests using cryptographically signed JSON Web Tokens (JWT).
18. Common Mistakes
Avoid these architectural anti-patterns:
- Premature Optimization: Designing a multi-region sharded database for an early-stage startup with 500 users. Build simple, modular monoliths first, and partition as traffic demands.
- Assuming Network Reliability: Assuming the network is fast, secure, and always online. Always configure connection timeouts, retries with exponential backoffs, and circuit breakers.
- Direct Database Sharing: Allowing two separate microservices to read and write directly to the same database tables. This bypasses API contracts, creating tight database coupling.
19. Implementation
Below is a Node.js/TypeScript implementation demonstrating a Cache-Aside pattern. It checks a Redis cache before falling back to a PostgreSQL query, and populates the cache on a miss:
20. Interview Questions
Q1 (Easy): What is the difference between horizontal and vertical scaling?
Answer: Vertical scaling (scaling up) means adding more power (CPU, RAM, Storage) to a single physical machine. It is simple but has a hardware limit and represents a single point of failure. Horizontal scaling (scaling out) means adding more machines to your network. It has no practical limit, but requires load balancers, data replication protocols, and handles network partitions.
Q2 (Medium): How does the Cache-Aside pattern work, and how does it deal with cache consistency?
Answer: In the Cache-Aside pattern, the application checks the cache first. On a hit, it returns the data. On a miss, it queries the database, writes the result to the cache, and returns it. To ensure consistency, when data is updated in the database, the corresponding cache key is immediately invalidated (deleted) rather than updated, preventing race conditions from writing stale data back to the cache.
Q3 (Hard): How do you design a stateful connection system (like WebSockets) to scale horizontally?
Answer: Scaling WebSockets horizontally requires addressing connection mapping. Since users establish persistent TCP connections to specific servers:
1. Load Balancer: Use an API gateway/load balancer that supports WebSocket protocols with consistent hashing based on client IP or user ID.
2. Pub/Sub Message Bus: Deploy a Redis Pub/Sub cluster or Kafka broker. When User A (connected to Server 1) sends a message to User B (connected to Server 2), Server 1 publishes the message to a channel. Server 2, subscribed to the channel, receives the event and pushes it to User B over the local TCP socket.
3. Presence Store: Store active connection routing maps (UserID -> ServerIP) in a centralized Redis cluster to quickly locate where to route messages.
21. Practice Exercises
Exercise 1 (Easy): Draw a Blog Architecture
Draw a block diagram of a basic blog platform that handles 10,000 views per month. Show where the database and web server live.
Exercise 2 (Medium): Horizontal WebSocket Redesign
Identify the modifications required to scale a single-server multiplayer game server (storing game room status in memory) to 10 nodes using Redis.
Exercise 3 (Hard): High QPS Telemetry System
Design a telemetry pipeline that accepts 1 million GPS logs per second from 10 million vehicles. Propose an architecture to ingest, validate, and store logs.
22. Challenge Problem
The Flash-Sale System Challenge:
You are designing a ticket booking platform for a premier world concert. You expect 1,000,000 concurrent ticket-buying requests in the first 5 minutes of release. There are only 10,000 tickets available.
Constraints:
- Strictly zero double-bookings are allowed.
- Database writes must not lock the main transaction table, which would cause API timeouts.
- Users must receive real-time queue notifications.
Outline an architecture that utilizes rate limiting, pre-allocated ticket tokens in a high-speed Redis database, asynchronous queuing (Kafka/RabbitMQ), and database read/write isolation to handle this traffic spike safely.
23. Summary
System Design is the discipline of planning how multiple distributed computers work together to deliver reliable, high-performance, and scalable software. It focuses on setting up boundaries, balancing trade-offs, and managing failure modes. Success in system design requires moving from simple code constructs (classes, methods) to distributed components (load balancers, caches, databases) connected via networking protocols.
24. Cheat Sheet
| Concept | Definition | Key Benefit | Standard Tool / Pattern |
|---|---|---|---|
| Horizontal Scaling | Adding more nodes to a system pool. | Infinite scaling capability. | AWS EC2 Cluster, Kubernetes Pods |
| Load Balancer | Distributes requests across servers. | Prevents hotspots, ensures routing. | NGINX, HAProxy, AWS ALB |
| Cache-Aside | Check cache, query DB on miss, write-back. | Decreases DB read pressure. | Redis, Memcached |
| Circuit Breaker | Fails requests fast when dependency is down. | Prevents cascading outages. | Resilience4j, Netflix Hystrix |
| Statelessness | Offloading session states to external stores. | Allows server nodes to scale down/up. | JWTs, Redis Session Store |
25. Quiz
Q1: Which architecture pattern stores no session records in the web server's RAM?
A) Stateful Architecture
B) Stateless Architecture
C) Monolithic Architecture
D) Thread-locked Architecture
Answer: B — Stateless architectures store no session state in server memory, instead offloading it to database/cache layers.
Q2: What is the main physical limitation of vertical scaling?
A) You must set up consistent hashing.
B) You run into hardware constraints (a single server's maximum CPU and RAM slot bounds).
C) It requires setting up multiple read-replicas.
D) It causes eventual consistency problems.
Answer: B — Vertical scaling is physically capped by the hardware limits of a single machine.
Q3: In the CAP Theorem, what does the "P" represent?
A) Performance latency limits
B) Primary database writes
C) Partition Tolerance
D) Protocol configurations
Answer: C — Partition Tolerance represents the system's ability to operate despite network messages being lost or delayed between nodes.
Q4: Which component is responsible for translating domain names into IP addresses?
A) Load Balancer
B) CDN
C) DNS
D) API Gateway
Answer: C — DNS (Domain Name System) translates names like google.com to IP addresses.
Q5: What is the primary purpose of a Content Delivery Network (CDN)?
A) Serve dynamic database write transactions
B) Cache static assets geographically closer to users to reduce latency
C) Terminate database locks
D) Balance horizontal web server nodes
Answer: B — CDNs store static assets (images, scripts) at edge nodes close to clients to reduce round-trip latency.
Q6: What failure pattern occurs when a dependencies' timeout causes multiple parent services to exhaust their thread pools?
A) Hotspot partitioning
B) Cascading failure
C) Thundering herd
D) Cache evictions
Answer: B — Cascading failures occur when a fault in one component triggers thread consumption and crashes upstream dependencies.
Q7: How does a circuit breaker defend a system?
A) It increases database connection limits dynamically.
B) It trips open and returns immediate errors when a dependency fails, protecting compute resources.
C) It encrypts network traffic.
D) It replicates tables between SQL nodes.
Answer: B — Circuit breakers intercept requests to a failing service, returning fast failures to prevent queue buildup and thread crashes.
Q8: Which mechanism prevents a single user's script from overloading an API gateway?
A) Database Indexes
B) Rate Limiter
C) CDN Caching
D) Code refactoring
Answer: B — Rate Limiters reject requests exceeding predefined thresholds, ensuring equal resource sharing.
Q9: What happens during a Cache Stampede?
A) The cache runs out of storage space and crashes.
B) A highly popular key expires and multiple concurrent client reads hit the database at once, causing it to freeze.
C) Write records bypass the cache entirely.
D) Packets loop indefinitely in Layer 3.
Answer: B — Cache stampede occurs when high concurrency reads bypass an expired cache key simultaneously, overloading the database.
Q10: Why is direct database sharing between microservices considered an anti-pattern?
A) It is impossible to configure in SQL.
B) It creates tight coupling at the database schema level, preventing independent deployments.
C) It reduces read latency.
D) It prevents CDN caching.
Answer: B — Sharing databases couples services at the data layer, making schema changes highly risky and breaking autonomy.
26. Further Reading
- Books: Designing Data-Intensive Applications by Martin Kleppmann (Chapters 1 and 2 cover scalability metrics).
- Engineering Blogs: Netflix Tech Blog (explaining their architecture transitions) and the High Scalability blog.
- RFCs: RFC 2616 (HTTP/1.1 fundamentals).
27. Next Lesson Preview
Now that you understand what system design is, we will dive into Networking & Web Fundamentals. In the next lesson, we explore the Internet Protocol (IP), learning how packets are logically addressed and routed across the global web using IPv4 and IPv6 protocols.
Key takeaways
- System design requires balanced trade-offs rather than "perfect" answers.
- Stateless architectures with external session caching form the baseline of scalable applications.
- Observe network latency and database contention, addressing bottlenecks asynchronously using queues.