Students in software engineering bootcamp programs usually build small-scale projects that require, at most, a few weeks of work. These projects don’t have to account for long-term considerations such as maintainability, scalability, and security. But when companies build applications they have to take into account several factors.
System design is the process of designing an application or service while taking into account user needs along with the product and business requirements. There are various types of systems that you may have to design as a software engineer. But the following three are the most common ones you’ll likely work on, especially earlier in your career:
- Application: A full application that addresses user needs, such as a URL shortener. It’s not common for an individual to design, develop, and maintain a full application at a company (unless it’s a very early-stage startup).
- Application feature: A specific feature addition or modification to an existing application, such as designing the feed for a social media application. Individual contributors are generally expected to work on these.
- Microservice: An application that’s not user-facing and is only used to facilitate the functioning of the overall system. For example, you may be asked to design or suggest a key-value store suitable for an existing system.
You need to consider both functional and non-functional requirements when designing any system. Let’s explore the differences between these two types of requirements using a URL shortener service such as Bit.ly as our example.
System Design Overview: Functional Requirements
Functional requirements define what a system is supposed to do or the specific features it must provide the users.
A URL shortener service may have some or all of the following functional requirements:
- Shorten URLs: The system must be able to take a long URL as input and generate a short URL.
- Redirect: When users access a shortened URL, the system must redirect them to the original long URL.
- Customization: Allow users to customize the shortened URL or provide an option to generate a random one.
- Analytics: Track the number of times each shortened URL is accessed and provide analytics for users.
- Expiration: Provide an option to set an expiration date for shortened URLs.
System Design Overview: Non-Functional Requirements
Non-functional requirements define the qualities or characteristics of the system. These include performance, reliability, and usability, rather than specific functionalities.
A URL shortener service may have the following non-functional requirements:
- Performance: The system should generate shortened URLs and redirect users quickly to ensure a seamless user experience.
- Scalability: The system should be able to handle a large volume of URL-shortening requests and redirections efficiently, especially during peak usage times.
- Reliability: The system should be highly available and reliable, with minimal downtime or service interruptions.
- Security: Ensures that the system is secure and resistant to attacks, such as URL manipulation or injection.
- Usability: The user interface should be intuitive and easy to use, allowing users to quickly shorten URLs and access analytics without confusion.
This article does a great job of explaining various non-functional requirements if you want to explore more.
When Should You Design Complex Systems?
Although it’s important to consider various requirements, tools, and technologies when designing systems, it’s equally important to not over-engineer systems. You’ll generally have some requirements guidelines when working on a team that maintains a product or service with existing users. System design interviews also have fairly good requirements (or at least the interviewer will nudge you towards desired requirements).
However, when you are developing a product or feature from scratch, it’s important to prototype quickly and gather feedback before tacking on a bunch of non-functional requirements. For example, Levels.fyi used Google Sheets as their backend in the beginning to scope out their idea before scaling it. If you design a large-scale system without considering user needs, you’ll end up with a beautiful, scalable system that no one uses.
In general, it’s better to start with simple design, tools, and technologies before designing for scale.
System Design Overview: Foundations
System design study resources cover tons of topics, such as scalability patterns, load balancers, and caching. But they are usually geared towards people who already have some experience with application development.
If you’re just starting out, it’s important to be aware of a few key concepts and ideas. We’ll be covering the following topics in the remainder of this article:
- Relevant computer components
- Single machine problems
- Distributed systems
Relevant Computer Components
You’ll encounter various terms like Content Delivery Networks (CDN), load balancer, cache, proxy, database. All of these terms refer to a computer or a network of computers running specialized applications.
The central processing unit (CPU) is often considered the “brain” of the computer. It mainly executes instructions and performs calculations required to run programs and processes.
Random-access memory (RAM) is the computer’s short-term memory. It is usually significantly faster than long-term storage. Temporary data and program instructions for the CPU are stored on the RAM.
Storage devices provide long-term, persistent storage for data, programs, and system files. Unlike the RAM, storage devices retain their data even when the power is turned off. They also have a much higher capacity than RAM.
The components are prioritized based on the type of application being run on a computer. For example, a database will likely have a much higher storage capacity than a server that processes user requests.
Single Machine Problems
You have probably designed and built a system like the above in your bootcamp program. It’s a standard structure that allows you to serve millions of users. But notice that all the requests and responses are being handled by a single server. And all of the data is being stored on a single database.
Single machines can cause issues down the road. The following are some of the issues that may crop up:
- Performance limit: A single server can host a limited number of CPUs, RAM, or storage. If you have a lot of requests, a single server simply won’t be able to handle them.
- Expensive component upgrades: More powerful CPUs and larger capacity RAM or storage devices can become very expensive. It’s often more efficient and cheaper to get additional systems.
- Scalability limit: The above two issues limit the scalability of the system. The server will either stop serving requests or it’ll be too expensive to upgrade it.
- No redundancy: If either the server or the database fails, it will cause a service outage for all of our users.
- Low availability: Availability refers to the proportion of time that a system is functional and working. If we have to upgrade the server or the database, we would have to suspend our service.
So how can we solve these issues? That’s where distributed systems come in.
Distributed Systems
A distributed system is a network of multiple independent computers (often referred to as nodes or hosts) that work together to achieve a common goal. You’ll have to configure how these computers communicate with each other when designing systems.
Although distributed systems address the issues with single machines, they introduce issues that need to be taken into account when designing systems.
Engineer Arnon Rotem-Gal-Oz described several fallacies of distributed systems (i.e., we can’t assume the following statements are true in a distributed system):
- The network is reliable
- Latency is zero
- Bandwidth is infinite
- The network is secure
- Topology doesn’t change
- There is one administrator
- Transport cost is zero
- The network is homogeneous
You’ll learn several system design patterns to address these fallacies but they aren’t often stated explicitly in study resources.
Now that you understand the foundations of system design, you can start preparing for system design interviews. You’ll find several resources in the linked article that will provide guidance on what to study.
Interested in Learning About Software Engineering Educational Opportunities?
Are you a software engineering enthusiast considering a career transition to the field? See what Flatiron School’s Software Engineering Bootcamp can do for you. Flatiron’s graduates have been hired by such companies as Apple, Microsoft, and Goldman Sachs, to name a few. Gain the skills needed for a software engineering career in as little as 15 weeks.