System Design is the process of deciding how different parts of a software system will work together to solve a business problem.
When we build a small application, we may mainly think about writing code. But when thousands or millions of users start using the application, many more questions appear:
- Where will the application run?
- Where will we store the data?
- How will thousands of users access it at the same time?
- What happens if a server goes down?
- How will we handle increasing traffic?
- How will we handle large amounts of data?
- How will different components communicate?
System Design helps us answer these questions and decide how the complete system should be built.
What Does System Design Mean?
Imagine we are building an online shopping application.
A very basic design could look like this:
flowchart LR
User --> API
API --> Database
API --> Payment
This design may work when there are only a small number of users.
But imagine that millions of users start using the application.
Now we need to think about multiple application servers, traffic distribution, database load, caching, failures and many other things.
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
LoadBalancer --> API3
API1 --> Database
API2 --> Database
API3 --> Database
API1 --> Cache
API2 --> Cache
API3 --> Cache
This is where System Design becomes important.
Why Do We Need System Design?
The main goal is to build a system that can continue working as users, requests and data increase.
Consider a banking application.
If only 100 users access the application, one application server may be enough.
But if millions of users access the application, one server can become overloaded.
We need to think about:
- How many servers are required?
- How will traffic be distributed?
- How will the database handle the load?
- What happens if one server fails?
- How can frequently requested data be served faster?
- How can the system recover from failures?
These are System Design questions.
Real-World Example
Let's take a simple Employee Management System.
A user opens the application and requests employee information.
sequenceDiagram
User->>API: Get employees
API->>Database: Query employees
Database-->>API: Employee data
API-->>User: JSON response
The ASP.NET Core API receives the request, queries SQL Server and returns the data.
For a small application, this architecture may be enough.
But imagine that thousands of users are requesting employee information at the same time.
Now the database may receive a very large number of requests.
We need to think about how to handle that traffic without making the application slow or unavailable.
ASP.NET Core Example
Let's create a simple Employee API.
[ApiController]
[Route("api/[controller]")]
public class EmployeesController : ControllerBase
{
private readonly AppDbContext _context;
public EmployeesController(AppDbContext context)
{
_context = context;
}
[HttpGet]
public async Task GetEmployees()
{
var employees = await _context.Employees
.AsNoTracking()
.ToListAsync();
return Ok(employees);
}
}
The Employee model can be:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Department { get; set; } = "";
public decimal Salary { get; set; }
}
The SQL Server table can be created using:
CREATE TABLE Employees
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(100) NOT NULL,
Department NVARCHAR(100) NOT NULL,
Salary DECIMAL(18,2) NOT NULL
);
When the client calls:
GET /api/employees
The API could return:
[
{
"id": 1,
"name": "Rahul",
"department": "IT",
"salary": 85000
},
{
"id": 2,
"name": "Priya",
"department": "Finance",
"salary": 90000
}
]
The code works, but System Design asks a bigger question:
Will this design continue to work when the application grows?
System Design Is More Than Writing Code
Writing a controller and SQL query is only one part of building a system.
We also need to think about the complete request flow.
flowchart LR
User --> LoadBalancer
LoadBalancer --> API
API --> Cache
API --> Database
API --> ExternalService
For example, if employee information is requested very frequently, we may not want every request to hit SQL Server.
We could first check the cache.
flowchart TD
Request --> Cache
Cache --> Check
Check --> Response
Check --> Database
Database --> Cache
Cache --> Response
If the data is already available in the cache, we can return it quickly.
If it is not available, the application can read the data from SQL Server and place it in the cache for future requests.
High-Level Design
High-Level Design focuses on the major components of the system and how they communicate with each other.
For example:
- Load Balancer
- Application Servers
- Database
- Cache
- Message Queue
- External Services
flowchart LR
User --> LoadBalancer
LoadBalancer --> API
API --> Cache
API --> Database
API --> MessageQueue
At this level, we are mainly interested in the overall architecture rather than individual classes and methods.
Low-Level Design
Low-Level Design focuses on implementation details.
For example:
- Classes
- Interfaces
- Methods
- Database tables
- Relationships
- API contracts
- Business logic
Our Employee class and EmployeesController are examples of low-level implementation details.
Real-World Example: Food Delivery System
Suppose we are designing a food delivery application.
The application may need to support:
- User registration and login
- Restaurant search
- Food ordering
- Payment
- Order tracking
- Delivery partner assignment
At a high level, we may have the following components:
flowchart LR
User --> API
API --> Restaurant
API --> Order
API --> Payment
API --> Delivery
Order --> Database
We have not written the complete implementation yet. We are first deciding how the major parts of the system should work together.
That is the basic idea behind System Design.
Questions to Ask Before Designing a System
Before jumping into architecture, understand the requirements.
- Who will use the system?
- What are the main features?
- How many users are expected?
- How many requests can arrive at the same time?
- How much data will be generated?
- How quickly should the system respond?
- What happens if a component fails?
- Does the system need to be available all the time?
The answers to these questions influence our design decisions.
Think About System Design Like a Real Business
Imagine a restaurant.
If only 10 customers arrive, one chef and one waiter may be enough.
But if 1,000 customers arrive, we need more chefs, more waiters, better order management and better coordination between the kitchen and serving area.
Software systems work in a similar way.
More users create more requests. More requests require more resources and better architecture.
Key Takeaways
- System Design defines how different parts of a software system work together.
- It is not only about writing code.
- It considers users, traffic, data and failures.
- High-Level Design focuses on major components.
- Low-Level Design focuses on implementation details.
- A design that works for a small application may not work when the application grows.
- Good System Design prepares the application for increasing traffic and changing requirements.
Conclusion
System Design is about looking at the complete picture instead of focusing only on one API, class or database query.
When we design a real-world application, we need to understand how the system will behave when the number of users increases, traffic grows, data becomes large and components fail.
In the next articles, we will take the important System Design concepts one by one and understand how they are used in real-world applications.