System design can look scary when you first start learning it.
You hear words like:
- Load Balancer
- Reverse Proxy
- Sharding
- Replication
- CDN
- Caching
- WebSockets
- Message Queues
- Microservices
- CAP Theorem
And you might think:
"Do I really need to understand all of this?"
The answer is yes — but not all at once.
The easiest way to learn system design is to understand how these concepts connect with each other.
In this article, we'll walk through 30 important system design concepts, starting from a simple client-server application and gradually building toward a highly scalable distributed system.
🏗️ The Big Picture
Imagine you're building an application like an e-commerce platform.
Initially:
User
↓
Application Server
↓
Database
As your application grows, you may eventually need:
┌── Application Server 1
User → CDN → Load ──┼── Application Server 2
└── Application Server 3
↓
Cache
↓
Database Cluster
↙ ↘
Replica 1 Replica 2
And eventually:
Client
↓
DNS
↓
CDN / Reverse Proxy
↓
Load Balancer
↓
API Gateway
↓
Microservices
↓
Cache / Message Queue
↓
Database
↓
Replication / Sharding
Let's understand how we get there.
1. Client-Server Architecture
Almost every web application starts with the same basic idea:
Client ↔ Server
The client is usually:
- Web browser
- Mobile application
- Desktop application
The server is responsible for:
- Processing requests
- Running business logic
- Accessing databases
- Returning responses
For example, when you open your banking application:
Mobile App
↓
"Show my balance"
↓
Server
↓
Database
↓
Account Balance
↓
Mobile App
The client doesn't need to know how the server calculates or retrieves the balance.
It only needs to know how to communicate with the server.
2. IP Address
Computers communicate with each other using IP addresses.
You can think of an IP address like a house address.
For example:
192.168.1.10
A server has an address so clients can find it.
But imagine having to remember:
142.250.195.14
every time you wanted to visit Google.
That's not practical.
This is where DNS comes in.
3. DNS
DNS stands for:
Domain Name System
DNS converts a human-friendly domain name into an IP address.
For example:
example.com
↓
DNS
↓
93.184.216.34
When you type a website into your browser:
https://example.com
your system needs to determine which server it should communicate with.
DNS provides that mapping.
Simple analogy
Think of DNS as your phone's contact list.
Instead of remembering someone's phone number, you save:
"Rahul"
Your phone finds the actual number.
DNS does something similar:
"example.com"
↓
IP Address
4. Proxy and Reverse Proxy
A proxy acts as an intermediary between a client and the internet.
Client
↓
Proxy
↓
Internet
A reverse proxy sits in front of your servers.
Client
↓
Reverse Proxy
↓
Backend Server
A reverse proxy can help with:
- Security
- SSL termination
- Traffic routing
- Load balancing
- Hiding backend servers
For example:
┌── Server 1
Client → Reverse ───┼── Server 2
Proxy └── Server 3
The client doesn't need to know which backend server actually processes the request.
5. Latency
Latency is the time taken for data to travel between systems.
For example:
User in India
↓
Server in USA
↓
Response
↓
User in India
The greater the physical distance, the more network delay can occur.
High latency makes applications feel slow.
How can we reduce latency?
One common solution is to place servers or cached content closer to users.
For example:
India User → India/Asia Server
USA User → USA Server
This is one reason globally distributed systems use multiple regions and CDNs.
6. HTTP / HTTPS
HTTP stands for:
Hypertext Transfer Protocol
It defines how clients and servers communicate over the web.
A typical interaction looks like:
Client
↓
HTTP Request
↓
Server
↓
HTTP Response
↓
Client
An HTTP request can contain:
- Method
- Headers
- URL
- Query parameters
- Request body
Common HTTP methods include:
GET
POST
PUT
PATCH
DELETE
What about HTTPS?
HTTPS is HTTP protected with encryption using TLS.
So instead of:
HTTP
↓
Plain communication
we have:
HTTPS
↓
Encrypted communication
This is especially important when handling:
- Passwords
- Payment information
- Personal information
- Authentication tokens
7. APIs
API stands for:
Application Programming Interface
An API provides a way for different pieces of software to communicate.
For example:
Mobile App
↓
GET /users/123
↓
API
↓
Database
↓
User Data
The mobile application doesn't need to know how the database works.
It simply asks the API:
"Give me user 123."
The server handles the internal work and returns a response.
Usually, modern web APIs exchange data using JSON.
Example:
{
"id": 123,
"name": "Rahul",
"email": "rahul@example.com"
}
8. REST API
REST stands for:
Representational State Transfer
REST is an architectural style commonly used for web APIs.
A REST API generally represents data as resources.
For example:
/users
/products
/orders
/payments
HTTP methods describe what we want to do.
| Method | Purpose |
|---|---|
| GET | Read data |
| POST | Create data |
| PUT | Replace/update data |
| PATCH | Partially update data |
| DELETE | Delete data |
Example:
GET /users/10
means:
Get user 10.
And:
POST /users
means:
Create a new user.
One important REST principle is statelessness.
Each request should contain the information needed to process it rather than relying on hidden server-side request state.
9. GraphQL
REST isn't the only way to build APIs.
Another popular approach is GraphQL.
With REST, you may have endpoints like:
GET /users/10
GET /users/10/posts
GET /users/10/orders
GraphQL allows the client to request the fields it actually needs.
For example:
{
user {
name
email
posts {
title
}
}
}
This can be useful when a frontend needs data from multiple related resources.
REST vs GraphQL
REST
Multiple endpoints
↓
Fixed response structures
GraphQL
Single API
↓
Client specifies required fields
GraphQL can reduce unnecessary data transfer, but it can also introduce additional server-side complexity and caching challenges.
10. Databases
Applications need somewhere to store persistent data.
That's the job of a database.
For example:
Application
↓
Database
↓
Users
Orders
Products
Payments
A database provides mechanisms for:
- Storing data
- Retrieving data
- Updating data
- Deleting data
- Maintaining consistency
- Managing concurrent access
Choosing the right database depends heavily on the application's requirements.
11. SQL vs NoSQL
Two major database categories are:
SQL
and
NoSQL
SQL databases
SQL databases typically use structured tables and relationships.
Examples:
- MySQL
- PostgreSQL
Example:
Users
----------------
id
name
email
SQL databases are often useful when you need:
- Strong relationships
- Transactions
- Structured schemas
- Strong consistency
SQL databases commonly emphasize ACID properties:
A — Atomicity
A transaction succeeds completely or fails completely.
C — Consistency
Data remains valid according to defined rules.
I — Isolation
Concurrent transactions don't improperly interfere with each other.
D — Durability
Committed data remains persisted.
NoSQL databases
NoSQL databases support several data models.
Examples include:
Key-Value
Document
Graph
Wide-Column
Popular technologies include:
- Redis
- MongoDB
- Cassandra
- Neo4j
NoSQL can be useful when applications require:
- Flexible data models
- Large-scale distribution
- High throughput
- Specific access patterns
The important lesson is:
Don't choose SQL or NoSQL because one is "better." Choose based on the requirements of your system.
12. Vertical Scaling
Suppose your application starts with one server:
Application
↓
Server
Traffic increases.
One option is to make that server more powerful.
For example:
4 GB RAM
↓
16 GB RAM
↓
32 GB RAM
or:
4 CPU cores
↓
16 CPU cores
This is called Vertical Scaling or Scaling Up.
Problem
A single server has limitations.
Eventually:
- Hardware reaches its maximum capacity
- Powerful hardware becomes expensive
- The server can become a single point of failure
So vertical scaling is useful, but it doesn't solve every scalability problem.
13. Horizontal Scaling
Instead of making one server more powerful, we can add more servers.
┌── Server 1
Client ─┼── Server 2
└── Server 3
This is Horizontal Scaling or Scaling Out.
Benefits include:
- More capacity
- Better fault tolerance
- Easier incremental scaling
- Reduced dependency on one machine
But now we have a new question:
Which server should receive each request?
That's where load balancers come in.
14. Load Balancer
A Load Balancer distributes incoming traffic across multiple servers.
┌── Server 1
Client → LB ─┼── Server 2
└── Server 3
Suppose 3,000 users send requests.
Instead of one server handling everything:
3000 requests
↓
Server
we can distribute the traffic:
3000 requests
↓
Load Balancer
↙ ↓ ↘
1000 1000 1000
↓ ↓ ↓
S1 S2 S3
Common load-balancing strategies include:
Round Robin
Requests are distributed sequentially.
Request 1 → Server 1
Request 2 → Server 2
Request 3 → Server 3
Request 4 → Server 1
Least Connections
Send traffic to the server currently handling fewer connections.
IP Hashing
Requests from the same client IP can be directed consistently according to a hash of the IP.
15. Database Indexing
Imagine a database contains:
10 million users
You run:
SELECT *
FROM users
WHERE email = 'rahul@example.com';
Without an appropriate index, the database may need to examine many rows.
An index provides a faster lookup structure.
Think about a physical book.
Without an index:
Page 1
Page 2
Page 3
...
Page 500
With an index:
"Databases" → Page 320
Much faster.
But indexes have a cost
Indexes can improve reads but require additional storage and maintenance when data changes.
So don't blindly index every column.
Index based on actual query patterns.
16. Database Replication
Suppose one database receives thousands of read requests.
Instead of forcing one database to handle everything, we can create replicas.
┌── Read Replica 1
Primary DB ──┼── Read Replica 2
└── Read Replica 3
Typically:
Writes
↓
Primary
↓
Replicas
↓
Reads
Replication can help with:
- Read scalability
- Availability
- Disaster recovery
A common pattern is:
POST /orders
↓
Primary DB
GET /orders
↓
Read Replica
However, depending on the replication model, replicas may temporarily lag behind the primary.
17. Database Sharding
Replication creates copies of data.
But what if the database itself becomes too large?
For example:
10 billion users
One database server may not be enough.
We can split the data across multiple databases.
This is called Sharding.
For example:
User ID 1-1M
↓
Shard 1
User ID 1M-2M
↓
Shard 2
User ID 2M-3M
↓
Shard 3
The system uses a sharding key to determine where data belongs.
A good sharding strategy can distribute:
- Storage
- Reads
- Writes
across multiple machines.
But poor shard-key selection can create hotspots where one shard receives much more traffic than others.
18. Vertical Partitioning
Sharding divides data primarily by rows.
Vertical partitioning divides data by columns.
Suppose we have:
User
--------------------------------
id
name
email
profile_picture
login_history
billing_address
payment_details
Maybe every request doesn't need all of this data.
We could split it:
User_Profile
----------------
id
name
email
profile_picture
User_Login
----------------
user_id
login_history
User_Billing
----------------
user_id
billing_address
payment_details
Now queries can retrieve only the information they need.
19. Caching
One of the most important performance techniques is caching.
Suppose the application frequently asks:
"What is user 123's profile?"
Without caching:
Application
↓
Database
↓
Response
If the same data is requested thousands of times, the database receives thousands of requests.
With caching:
Application
↓
Cache
↓
Data
A common pattern is Cache Aside.
Cache Aside
Request
↓
Check Cache
↓
Found? ── Yes → Return Data
|
No
↓
Database
↓
Store in Cache
↓
Return Data
Popular caching technologies include:
- Redis
- Memcached
Caches often use a TTL (Time To Live) so old data can expire.
20. Denormalization
Database normalization helps reduce duplicate data.
But sometimes normalized data requires many JOIN operations.
For read-heavy applications, we may intentionally duplicate some information.
This is called Denormalization.
For example:
Normalized
Users
Orders
Products
To display an order, you may need multiple joins.
Denormalized
OrderView
--------------------------------
order_id
user_name
user_email
product_name
amount
Now reading the data can be simpler and faster.
Trade-off
Denormalization can improve read performance, but:
- More storage is required
- Data duplication increases
- Updates become more complicated
System design is usually about understanding these trade-offs.
21. CAP Theorem
When your application becomes distributed across multiple machines, you encounter the CAP Theorem.
CAP represents:
C = Consistency
A = Availability
P = Partition Tolerance
Consistency
Every read receives the latest available data.
Availability
The system continues responding to requests.
Partition Tolerance
The system continues operating even when communication between nodes is disrupted.
The important idea is that when a network partition occurs, a distributed system has to make a trade-off between consistency and availability.
This leads to systems commonly being discussed as:
CP
or:
AP
Eventual Consistency
Some distributed systems allow data to be temporarily different across nodes.
Eventually:
Node A → Updated
Node B → Old
Node C → Old
↓
Synchronization
↓
Node A → Updated
Node B → Updated
Node C → Updated
This is called Eventual Consistency.
22. Blob Storage
Applications don't only store database records.
They also store:
- Images
- Videos
- PDFs
- Audio files
- Documents
- Backups
Storing huge files directly inside traditional database tables is often not the best approach.
Instead, we can use Blob/Object Storage.
Examples include cloud object-storage services such as Amazon S3.
A typical architecture might be:
User
↓
Application
↓
Object Storage
↓
Image / Video / PDF
The database can store metadata:
file_id
user_id
file_url
file_type
created_at
while the actual large file lives in object storage.
23. CDN
CDN stands for:
Content Delivery Network
Imagine a user in India requests a large image from a server located in the USA.
India User
↓
USA Server
↓
Image
The physical distance can increase latency.
A CDN places cached copies of content closer to users.
Origin Server
↓
┌──────────┼──────────┐
↓ ↓ ↓
India Europe USA
Edge Edge Edge
↓
User
CDNs are particularly useful for:
- Images
- JavaScript
- CSS
- Videos
- Static files
The goal is simple:
Serve content from a location closer to the user.
24. WebSockets
HTTP generally follows a request-response model:
Client → Request
Server → Response
But what if the server needs to send data to the client immediately?
Examples:
- Chat applications
- Live notifications
- Online games
- Stock dashboards
- Real-time collaboration
Polling would require the client to repeatedly ask:
"Anything new?"
"Anything new?"
"Anything new?"
WebSockets provide a persistent connection.
Client ←────────→ Server
Connection
stays open
Now the server can push events to the client when something happens.
25. Webhooks
WebSockets are useful for real-time communication between a client and server.
But sometimes one server needs to notify another server about an event.
That's where Webhooks are useful.
For example:
Payment Provider
↓
Payment Successful
↓
POST /webhook/payment
↓
Your Backend
Instead of repeatedly asking:
"Has the payment completed?"
your application waits for the payment provider to notify it.
Webhooks are commonly used for:
- Payment notifications
- GitHub events
- Messaging events
- Subscription events
- CI/CD triggers
26. Microservices
Imagine an e-commerce application containing:
Authentication
Payments
Orders
Inventory
Shipping
Notifications
In a monolithic architecture, all these components may exist inside one application.
Monolith
┌──────────────────────┐
│ Auth │
│ Payments │
│ Orders │
│ Inventory │
│ Shipping │
└──────────────────────┘
As the system grows, maintaining and deploying everything together can become difficult.
Microservices break the system into smaller services.
Auth Service
↓
Payment Service
↓
Order Service
↓
Inventory Service
↓
Notification Service
Each service can potentially:
- Be deployed independently
- Scale independently
- Own its business logic
- Have its own data store
However, microservices also introduce complexity:
- Network communication
- Distributed debugging
- Data consistency
- Service discovery
- Deployment management
So microservices aren't automatically better than monoliths.
27. Message Queues
Suppose the order service needs the payment service to process something.
A direct request might look like:
Order Service
↓
Payment Service
What happens if the payment service is temporarily unavailable?
The order service may have to wait or fail.
A message queue introduces asynchronous communication.
Producer
↓
Message Queue
↓
Consumer
Example:
Order Service
↓
"Process Payment"
↓
Message Queue
↓
Payment Service
The queue temporarily stores the message until the consumer can process it.
Popular technologies include:
- Apache Kafka
- RabbitMQ
- Amazon SQS
Message queues can help with:
- Decoupling services
- Handling traffic spikes
- Asynchronous processing
- Improving fault tolerance
28. Rate Limiting
Imagine someone sends:
10,000 requests/second
to your API.
Without protection, your application may become overloaded.
Rate limiting controls how many requests a client can make during a period.
For example:
100 requests / minute
If the client exceeds the limit:
HTTP 429
Too Many Requests
Common approaches include:
Fixed Window
100 requests
per minute
Sliding Window
The system evaluates requests over a moving time window.
Token Bucket
Clients receive tokens at a controlled rate and spend a token for each request.
Rate limiting protects:
- Server resources
- APIs
- Databases
- Cloud costs
- System availability
29. API Gateway
As microservices grow, exposing every service directly to clients becomes difficult.
Instead, we can introduce an API Gateway.
┌── Auth Service
│
Client → Gateway ─┼── Order Service
│
├── Payment Service
│
└── Inventory Service
The API Gateway becomes the entry point for clients.
It can handle things such as:
- Authentication
- Authorization
- Rate limiting
- Routing
- Logging
- Monitoring
- Request transformation
For example:
GET /orders/123
↓
API Gateway
↓
Order Service
↓
Response
This keeps clients from needing to know the internal structure of the microservices architecture.
30. Idempotency
The final concept is extremely important when building reliable distributed systems.
Imagine a user clicks:
"Pay ₹10,000"
The request reaches the server.
But the network times out.
The user doesn't know whether the payment succeeded.
So they click the button again.
Now the server receives:
Payment Request
Payment Request
You don't want the user to be charged twice.
This is where Idempotency helps.
The client can send a unique idempotency key:
Idempotency-Key:
payment_12345
The server stores the result associated with that key.
When the same request arrives again:
payment_12345
↓
Already processed?
↓
YES
↓
Return previous result
Instead of processing the payment again.
This is especially important for:
- Payments
- Orders
- Subscriptions
- Financial transactions
- Distributed retries
🔗 How These 30 Concepts Connect
The most important thing isn't memorizing 30 definitions.
It's understanding how they work together.
Imagine you're building a large e-commerce application.
A user opens your application:
1. Client
↓
2. DNS
↓
3. CDN / Reverse Proxy
↓
4. Load Balancer
↓
5. API Gateway
↓
6. Microservices
The application may use:
7. REST API / GraphQL
↓
8. Cache
↓
9. Database
As traffic grows:
Horizontal Scaling
↓
Load Balancer
↓
Multiple Servers
As database traffic grows:
Indexing
↓
Replication
↓
Sharding
↓
Partitioning
For large files:
Blob Storage
↓
CDN
For real-time communication:
WebSockets
For external events:
Webhooks
For asynchronous processing:
Message Queue
For protecting APIs:
Rate Limiting
For reliable distributed operations:
Idempotency
And when everything becomes distributed:
CAP Theorem
+
Consistency
+
Availability
+
Fault Tolerance
🧠 A Simple Learning Order
If you're new to system design, don't try to learn all 30 concepts in one day.
I recommend this order:
Level 1 — Fundamentals
Client-Server
↓
IP Address
↓
DNS
↓
HTTP/HTTPS
↓
API
↓
REST API
Level 2 — Database
SQL vs NoSQL
↓
Indexing
↓
Replication
↓
Sharding
↓
Partitioning
Level 3 — Performance
Latency
↓
Caching
↓
CDN
↓
Load Balancer
Level 4 — Distributed Systems
CAP Theorem
↓
Eventual Consistency
↓
Message Queue
↓
Microservices
Level 5 — Advanced Communication
WebSockets
↓
Webhooks
↓
API Gateway
↓
Rate Limiting
↓
Idempotency
🎯 Final Takeaway
System design becomes much easier when you stop treating it as a collection of complicated terms.
Instead, think about the problems you're trying to solve.
Problem: Too much traffic?
Use:
Horizontal Scaling
+
Load Balancer
Problem: Database reads are slow?
Consider:
Indexing
+
Caching
+
Replication
Problem: Database is too large?
Consider:
Sharding
+
Partitioning
Problem: Users are far from your servers?
Consider:
CDN
+
Multiple Regions
Problem: Services are tightly coupled?
Consider:
Microservices
+
Message Queues
Problem: API is being abused?
Consider:
Rate Limiting
+
API Gateway
Problem: Need real-time communication?
Consider:
WebSockets
Problem: External service needs to notify you?
Consider:
Webhooks
Problem: Duplicate requests?
Consider:
Idempotency
The real skill in system design is not knowing every technology.
It's knowing which problem you're solving, which trade-off you're accepting, and why a particular architecture makes sense.
🚀 30 Concepts — Quick Revision
| # | Concept | Main Purpose |
|---|---|---|
| 1 | Client-Server | Application communication |
| 2 | IP Address | Identify machines |
| 3 | DNS | Domain → IP mapping |
| 4 | Proxy / Reverse Proxy | Traffic intermediary |
| 5 | Latency | Measure communication delay |
| 6 | HTTP/HTTPS | Web communication |
| 7 | API | Software communication interface |
| 8 | REST API | Resource-based HTTP API |
| 9 | GraphQL | Flexible data querying |
| 10 | Database | Persistent data storage |
| 11 | SQL vs NoSQL | Database choice |
| 12 | Vertical Scaling | Make one server stronger |
| 13 | Horizontal Scaling | Add more servers |
| 14 | Load Balancer | Distribute traffic |
| 15 | Indexing | Faster database queries |
| 16 | Replication | Copy database data |
| 17 | Sharding | Split data across servers |
| 18 | Vertical Partitioning | Split columns/data by usage |
| 19 | Caching | Faster repeated access |
| 20 | Denormalization | Optimize read-heavy workloads |
| 21 | CAP Theorem | Distributed-system trade-offs |
| 22 | Blob Storage | Store large files |
| 23 | CDN | Deliver content closer to users |
| 24 | WebSockets | Real-time communication |
| 25 | Webhooks | Event notifications |
| 26 | Microservices | Independently deployable services |
| 27 | Message Queues | Asynchronous communication |
| 28 | Rate Limiting | Control request volume |
| 29 | API Gateway | Central API entry point |
| 30 | Idempotency | Prevent duplicate operations |
💡 One Last Tip
When preparing for a system design interview, don't just memorize:
"What is sharding?"
Instead ask yourself:
"My database has become too large. What options do I have?"
Then think:
Vertical Scaling
↓
Replication
↓
Sharding
↓
Caching
↓
Partitioning
That's how system design starts becoming intuitive.
Learn the problem first.
Then learn the solution.
Then understand the trade-offs.
That's the real foundation of system design. 🚀
Reference
This article is an original learning-oriented rewrite based on the system design concepts covered in AlgoMaster's article, "System Design was HARD until I Learned these 30 Concepts" by Ashish Pratap Singh.
Top comments (0)