← All writing
systemsarchitecturefundamentals

System Design 101: Client–Server Architecture, the CAP Theorem, and Why They Matter

·7 min read·Utkarsh Khanna
A client connecting through a load balancer to multiple servers
On this page

If you've ever wondered how apps like WhatsApp, Instagram, Netflix, or Amazon handle millions of users simultaneously, you're already asking a system design question.

System design isn't just for senior engineers. It's about understanding how software works beyond writing code. Once you grasp the basics, you'll start looking at every application differently.

In this article, we'll cover three fundamental concepts every beginner should know:

  • How the client–server model works
  • What the CAP theorem is
  • Why distributed systems have to make difficult trade-offs

Let's start with something you already use every day.

Imagine Ordering Food

Suppose you're hungry and open a food delivery app. You search for a burger, add it to your cart, and tap "Place Order." Seems simple, right?

Behind the scenes, dozens of systems are working together within milliseconds. Here's what actually happens:

  1. Your phone sends a request.
  2. A server receives that request.
  3. The server checks whether the restaurant is open.
  4. It verifies ingredient availability.
  5. It processes payment.
  6. It stores the order in a database.
  7. It notifies the restaurant.
  8. It updates the delivery partner.
  9. It sends confirmation back to your phone.

Your phone only shows a loading spinner. Everything else happens on servers. This brings us to our first concept.

What Is a Client?

A client is simply something that requests a service. Examples include:

  • Your smartphone
  • A web browser
  • A desktop application
  • Even another server

The client's job is to ask for information. It does not usually contain all the application logic or all the data.

Think of the client as a customer in a restaurant. The customer places an order. They don't cook the food.

What Is a Server?

A server is a computer whose job is to respond to requests. When the client asks for something, the server decides what should happen.

For example, you visit:

https://example.com/profile

The browser asks: "Can I have this user's profile?" The server then:

  • Checks who you are.
  • Verifies permissions.
  • Fetches data from the database.
  • Returns the profile.

The client simply displays it beautifully.

Client–Server Communication

Let's walk through a simple login.

Step 1 — The client sends a request

You type a username and password, then press Login. The client sends something like:

POST /login

{
  "username": "john",
  "password": "mypassword"
}

Step 2 — The server checks

The server receives the request and checks:

  • Does this user exist?
  • Is the password correct?

Step 3 — The server responds

If everything matches, the server replies with Login Successful along with a token.

Step 4 — The client stores the token

The client stores the token and uses it for future requests. That's all. Every app you use follows this same pattern.

Why Don't Apps Store Everything on Your Phone?

Imagine Instagram storing every user's photos on your phone. There are billions of images. Impossible.

Instead, your phone requests only what you need:

Show me my feed.

The server sends only the next few posts. This keeps apps fast and lightweight.

What Happens When Millions of Users Open the Same App?

Now imagine New Year's Eve. Millions of users open WhatsApp simultaneously. Can one server handle everyone? Not really — eventually it becomes overloaded.

So companies use multiple servers. Instead of this:

Users
  |
Server

They build:

Users
  |
Load Balancer
  |
Server 1
Server 2
Server 3
Server 4

Each server handles part of the traffic. This process is called horizontal scaling — instead of making one server stronger, we add more servers. But now another problem appears.

Keeping Multiple Servers in Sync

Suppose there are three servers: Server A, Server B, and Server C.

You upload a profile picture. Server A updates it. A second later your friend requests your profile, and their request reaches Server C — but Server C hasn't received the update yet.

Your friend still sees the old picture. Different servers now have different information. This is one of the biggest challenges in distributed systems, and it leads us to the CAP theorem.

What Is the CAP Theorem?

The CAP theorem says that in a distributed system, you cannot guarantee all three of these properties at the same time:

  • Consistency
  • Availability
  • Partition tolerance

You can only fully guarantee two. Let's understand each one.

C — Consistency

Consistency means every server returns the same data. Imagine updating your Instagram bio. Immediately after updating — every device, every region, every server — shows the exact same bio. No exceptions. Everyone sees identical data.

A — Availability

Availability means every request gets a response, even if something breaks. Even if one server crashes, the system still answers. Maybe the answer is slightly outdated, but the user doesn't wait forever.

Think of Google Search. Even if one data center fails, Google still returns results.

P — Partition Tolerance

A partition happens when servers cannot communicate. Imagine two data centers — one in India, one in the USA. Suddenly the network link between them fails. Now they cannot exchange information. Both are still running, but they are isolated. This is called a network partition.

Large distributed systems assume this can happen, because networks fail. Always.

Why Can't We Have All Three?

Imagine you have two servers, Server A and Server B. They normally stay synchronized. Now the network connection breaks:

A   X   B

A user updates data on Server A. Another user reads from Server B. You now have two choices.

Option 1 — Choose consistency

Wait until both servers reconnect. Both users always see identical data, so consistency is preserved. But users may receive errors or timeouts — availability is sacrificed.

Option 2 — Choose availability

Allow both servers to continue working independently. Users always receive responses, so availability is preserved. But different users may temporarily see different data — consistency is sacrificed.

That's the central idea of the CAP theorem. When a network partition exists, you must choose between consistency and availability. You cannot perfectly guarantee both simultaneously.

Real-World Trade-offs

Banking

Imagine transferring ₹10,000. You never want two balances to exist. Banks prioritize consistency and partition tolerance. If systems cannot synchronize, they may temporarily reject transactions — incorrect balances are unacceptable.

Social Media

Suppose you update your profile picture. One friend sees it immediately, another sees it five seconds later. No big deal. Platforms like Instagram or Facebook usually prioritize availability and partition tolerance. Small delays are acceptable.

Online Shopping

Suppose only one laptop remains and two people attempt to buy it simultaneously. Most systems lean toward consistency here. Overselling products creates major problems.

Eventual Consistency

Many modern systems use something called eventual consistency. Right now:

Server A → New Photo
Server B → Old Photo

After a few seconds:

Server A → New Photo
Server B → New Photo

Eventually, every server agrees. Temporary differences are acceptable. This approach lets systems stay highly available while still converging to the same state.

Why Should Beginners Care?

You don't need to build Netflix tomorrow. But understanding these concepts changes how you think about software. Instead of asking "How do I write this function?", you'll start asking:

  • Where should this data live?
  • How will thousands of users access it?
  • What happens if a server crashes?
  • How do multiple servers stay synchronized?
  • Which trade-offs make sense for my application?

These are the questions system design tries to answer.

Final Thoughts

System design isn't about memorizing fancy architectures. It's about solving practical engineering problems at scale.

The client–server model teaches us how applications communicate. Distributed systems teach us that one server isn't enough forever. The CAP theorem reminds us that every large system involves trade-offs — you cannot optimize everything simultaneously, so engineers make choices based on the needs of their application.

The best system designers aren't the ones who know the most technologies — they're the ones who understand why those technologies exist in the first place.

If you're just beginning your system design journey, don't worry about microservices, distributed databases, or message queues yet. Build a strong understanding of these fundamentals first. Once these ideas click, every advanced topic becomes much easier to understand.

Keep reading