FAANG System Design Mastery
System Design Fundamentals
First, Ask the Right Questions
Before you can build anything, you need to know what you're building. In system design, this starts with understanding requirements. Think of it like building a house. You wouldn't just start laying bricks. You'd first ask: How many bedrooms? How many bathrooms? Should it withstand hurricanes? These questions define the blueprints.
System requirements are broken down into two main categories: functional and non-functional.
Functional requirements are about what the system does. They are the specific features the user interacts with. For a social media app, a functional requirement might be "users can upload a photo."
Non-functional requirements are about how the system performs. They define its qualities, like speed, security, and reliability. For that same app, a non-functional requirement could be "photos must upload in under two seconds."
Getting these requirements right is the most critical step. A system that does amazing things but is slow, insecure, or constantly crashing isn't a good system. Both types of requirements work together to define success.
| Requirement Type | Description | Example (E-commerce Site) |
|---|---|---|
| Functional | What the system must do. | Users can add items to a shopping cart. |
| Non-functional | How the system must be. | The website must load in under 3 seconds. |
Blueprints for Software
Once you know the requirements, you need a plan for how to structure the system. This is where architectural patterns come in. They are like standard blueprints that provide a proven way to organize your code and components. You don't have to reinvent the wheel every time you build something new.
Two of the most common patterns are the monolithic and microservices architectures.
Monolith
noun
A single, unified application where all components are interconnected and interdependent.
Imagine a restaurant where one single chef does everything: takes orders, cooks the appetizers, grills the steaks, bakes the dessert, and washes the dishes. That's a monolithic architecture. All the functions are tightly bundled into one large application. It's simple to start with, but if the chef gets overwhelmed, the whole restaurant slows down.
Microservices
noun
An architectural style that structures an application as a collection of small, independent services.
Now picture a large restaurant with a team of specialized chefs. One handles grilling, another handles desserts, and a third focuses on salads. They work independently but coordinate to create a complete meal. This is a microservices architecture. Each service handles one specific job, and they communicate with each other. If the dessert chef is busy, it doesn't stop the grill chef from sending out steaks.
Planning for Growth
Your system is built, but what happens when it becomes popular? A service designed for 100 users might crash when 100,000 show up. The ability to handle this growth is called scalability. There are two primary ways to scale a system: vertically and horizontally.
Vertical scaling (scaling up) means making your existing server more powerful. You add more RAM, a faster CPU, or more storage. It's like a weightlifter training to lift heavier weights.
Horizontal scaling (scaling out) means adding more servers to share the load. Instead of one powerful server, you have many standard servers working together. It's like hiring more people to complete a large project.
Horizontal scaling is often preferred for large-scale applications because it's more flexible and doesn't have an upper limit like a single machine does. You can keep adding more servers as your user base grows.
The Art of the Trade-Off
There is no such thing as a perfect system. Every design choice comes with benefits and drawbacks. This is the core challenge of system design: making intelligent trade-offs. You are constantly balancing competing priorities, like performance vs. cost, or consistency vs. availability.
System design isn’t about memorizing patterns—it's about deeply understanding trade-offs and making informed decisions that suit your application's unique context.
Let's revisit our architecture patterns. A monolith is simple and fast to develop initially (a pro), but it's harder to scale and maintain as it grows (a con). Microservices are excellent for scalability and allow teams to work independently (pros), but they introduce complexity in managing communication between services (a con).
Which one is better? It depends entirely on your requirements, your team's size, and your long-term goals. A small startup might choose a monolith to launch quickly, while a massive company like Netflix relies on microservices to manage its complex platform. Choosing the right path means understanding what you're gaining and what you're giving up with each decision.
This principle applies to every layer of the system. Do you use a database that ensures every piece of data is perfectly consistent but might be a bit slower? Or one that is lightning fast but occasionally might serve slightly stale data? These are the kinds of trade-offs engineers weigh every day.
A social media platform's requirement that "the service must support 1 million concurrent users" is an example of what type of requirement?
In a monolithic architecture, a failure in one component is more likely to bring down the entire system.
These fundamentals—understanding requirements, choosing architectural patterns, planning for scale, and making smart trade-offs—are the building blocks for creating robust and effective systems.