System design: An overview
System design refers to the process of creating a high-level plan or blueprint for how a software
system should be built.
In the world of web applications, this is required when applications grow in users and traffic,
because the systems that support them also need to grow.
System design can be divided into two main categories: High-level and low level.
So let's break them down.
High-level system design (also known as architectural design or system architecture)
High-level design is usually what people mean when they say system design.
Large systems are usually built as distributed systems, which often require a lot of computers
(servers) working together to achieve a common goal. By dividing the workload among multiple
computers, distributed systems can improve performance, scalability, and fault tolerance.
Before we dive into that though, we need to understand some key concepts related to
distributed systems:
Node
In a distributed system, a node can be a computer, server, or device that has its own resources
(processing power, memory, and storage) and usually its own IP address.
When you think about the backend application code you write, it usually gets hosted on a node
when it’s live. Nodes can also host databases, services, or any other system component.
Nodes operate independently from each other and communicate with other nodes through a
network to exchange information and coordinate what they’re doing.
Node Cluster
Multiple nodes that work together and pool resources is called a cluster.
The nodes that live in these clusters usually run the exact same applications, and a cluster of
nodes is treated as a single unit. Clusters have to balance the load of requests they receive
amongst its nodes to ensure that no single nodes are overwhelmed or crash.
Network
The communication between nodes in a distributed system occurs over a network, which can be
a local area network (LAN) or a wide area network (WAN), such as the internet.
The network enables nodes to send and receive messages or data, allowing them to collaborate
on tasks.
Scalability
One of the main advantages of distributed systems is their ability to scale. As the workload
increases and the number of users grows, additional nodes can be added to the system to
handle the increased demand.
This allows the system to maintain its performance and availability, even as it grows in size and
complexity.
Systems will need to scale up and down the amount of nodes depending on how much traffic is
currently going through the system.
For example
E-commerce applications may need more nodes during Black Friday sales, versus their regular
shopping season.
This means that they’ll need to be able to scale up when there is a huge spike in traffic, or scale
down when that seasonal traffic is gone.
Consistency
In a distributed system, data is constantly flowing through multiple nodes and databases.
Maintaining consistency of data across all nodes can be challenging and usually there is a
tradeoff of how readily available that data is to those requesting it.
Various consistency models, such as eventual consistency or strong consistency, are used to
define the level of synchronization and data accuracy across different nodes. Systems like banks
need near immediate consistency of banking data since accuracy about money is a must have.
Availability
In a distributed system, there are often millions of requests for data coming from users,
application code, services etc. Retrieving and storing data, running application code and all the
other things that happen in a system is often time consuming.
Users on the other hand are not sympathetic to the needs of our system and want things to
happen fast, which means that many systems will need to prioritize being able to show them
stale data, even if it’s slightly off, rather than wait until they’re sure the data is consistent.
The tradeoff for higher availability is strong consistency, and most systems that prioritize
availability can ensure that eventually the data will be consistent, but it’s not the priority.
An example of this would be a messaging application, where users expect to be able to use it at
anytime rather than how up to date all the information about the messages themselves are.
Partition tolerance
Distributed systems are designed to be resilient when failures happen, such as hardware
malfunctions, network issues, or software bugs. If one node fails, the other nodes can continue
to operate, ensuring that the system remains functional.
In the world of distributed systems, partition tolerance is a must have. Traffic spikes, servers
crash, bad code gets pushed, security breaches happen and all things under the sun to bring
your system to its knees.
As a result, we need to design our systems to be resilient to these things through back up
nodes, clustering, and other techniques!
High level system design is incredibly important for every developer to start learning. You can
read my article that does a deep dive into System Design here.
You can also take my course on the basics of system design here.
Low-level system design (also known as detailed design or component design)
This stage involves breaking down the high-level design into smaller, more detailed
components, modules, or classes. It includes defining algorithms, data structures, and interfaces
for each component or module.
Low-level design is concerned with the specific implementation details of the system, such as
coding and programming languages.
When building an application, you’ll see a lot of early discussions around how to architect the
codebase.
This is why in all our courses that teach web development at Zero To Mastery, we teach low
level design in the respective domain!
This means that if you learn React with me or React-Native with Mo, you’ll learn low level
architecture patterns for how to structure the applications we build together.
There is a lot of bad software out there but we want to teach you how to write good software
partially because it'll help you stand out from your peers but it'll also just save you many
headaches down the road by doing things the "right" way in the first place 🙂. Many courses
don't bother teaching you this but that's a miss in our opinion.
tl;dr
All in all, you don’t need to learn system design through a computer science degree. In fact, a
lot of it doesn’t make sense until you work on a real application at scale to really solidify these
concepts into a real world system.
Regardless, it’s still incredibly valuable to learn the theoretical side of system design to better
understand how all of web development comes together!