Skip to content
Unverified — AI-generated content. Help verify this page

Client-Server Architecture

Every application you use — Google, Instagram, Spotify, your banking app — follows the same fundamental pattern: one piece of software (the client) asks for something, and another piece of software (the server) provides it. This pattern is called client-server architecture, and it is the foundation of virtually all modern software.

If you have ever opened a browser and loaded a webpage, you have used client-server architecture. The browser is the client. The computer that sent you the webpage is the server. Understanding this pattern deeply is the first step toward designing real systems.

What Is a Client? What Is a Server?

A client is any software that initiates a request. A server is any software that responds to requests. That is it. There is nothing magic about servers — they are just programs that listen for incoming requests and send back responses.

Important: "client" and "server" are roles, not physical machines. The same computer can be a client in one interaction and a server in another. When your backend server queries a database, your backend is the client and the database is the server.

The Evolution of Architecture

Software architecture has evolved over decades. Understanding this history helps you understand why systems are designed the way they are today.

Stage 1: The Monolith (Everything on One Machine)

In the beginning, there was one computer that did everything. The user interface, the business logic, and the data storage all ran on the same machine. This is called a monolith.

Examples: Early desktop applications like Microsoft Word, Excel, or a game installed on your computer. Everything runs locally. No network involved.

Advantages:

  • Simple to develop and deploy
  • No network latency
  • No network failures to handle
  • Works offline

Disadvantages:

  • Cannot share data between users easily
  • Cannot scale beyond one machine
  • Every user needs the software installed
  • Updates require every user to download the new version

Stage 2: Two-Tier Architecture (Client + Database)

As networks became available, developers split the monolith into two layers (tiers). The application ran on the user's computer, but the data lived on a shared database server.

Examples: Enterprise applications in the 1990s. A Visual Basic app on each employee's computer connecting directly to a shared Oracle database.

Advantages:

  • Multiple users can share data
  • Data lives in one place (single source of truth)

Disadvantages:

  • Clients send raw SQL queries to the database (security nightmare)
  • Business logic is duplicated across every client
  • Updating business logic means updating every client machine
  • Database connections scale poorly (each client holds a connection)

Stage 3: Three-Tier Architecture (The Modern Standard)

The solution was to add a middle layer between the client and the database. This application server (or "backend") contains all the business logic. The client only talks to the application server, never directly to the database.

This is the architecture behind almost every web application you use today. When you open Instagram:

  1. Tier 1 (Presentation): Your phone's Instagram app or the web browser
  2. Tier 2 (Application): Instagram's servers that handle your requests
  3. Tier 3 (Data): Instagram's databases that store posts, users, and comments

Advantages:

  • Clients never touch the database (security)
  • Business logic lives in one place (easy to update)
  • Each tier can scale independently
  • Different clients (web, mobile, API) can share the same backend

Disadvantages:

  • More complexity than a monolith
  • Network latency between tiers
  • More things that can fail

Stage 4: N-Tier Architecture (Microservices and Beyond)

As systems grow, the three-tier model evolves into N-tier — where the application layer splits into many specialized services. This is the world of microservices, message queues, caches, and CDNs.

For a deep exploration of how this evolves at massive scale, see the Zero to Million Users page and the Microservices section.

Thin Clients vs Thick Clients

One of the most important design decisions is how much work the client does versus the server.

Thin Client

A thin client does very little processing. It basically just displays what the server sends. The server does all the heavy lifting.

Examples:

  • Server-side rendered websites (the server generates full HTML pages)
  • Terminal/SSH sessions
  • Google Stadia (game runs on server, client just displays the video stream)
  • Chromebook (most processing happens in the cloud)

Advantages: Easy to update (change server only), works on weak devices, less attack surface on client

Disadvantages: Requires constant network connection, server does more work, higher latency for interactions

Thick Client (Rich Client)

A thick client does significant processing locally. The server mainly provides data through APIs.

Examples:

  • Single Page Applications (React, Vue, Angular)
  • Native mobile apps
  • Desktop applications like Slack or VS Code
  • Video games

Advantages: Faster interactions (no round trip for every click), works offline partially, lower server load

Disadvantages: More complex client code, harder to update (app store releases), more attack surface, larger download

The Spectrum in Practice

Most modern applications live somewhere in between:

ApplicationClient ThicknessWhy
Google DocsThickReal-time editing needs client-side logic
NetflixMediumVideo playback is local, content discovery is server-rendered
Banking AppThinSecurity matters more than snappy UI
VS CodeThickFull IDE running locally
Google SearchThinServer generates results, client just displays them

Stateful vs Stateless Servers

This is one of the most important concepts in system design. It determines how easily your system can scale.

Stateful Server

A stateful server remembers things about each client between requests. It stores session data in memory. If you are talking to Server A, your next request must also go to Server A because that is where your session lives.

Problem: If Server A dies, the session is lost. The user has to log in again and their cart is empty. Also, you cannot easily add more servers because each user is "stuck" on their server.

Stateless Server

A stateless server does not remember anything between requests. Every request contains all the information the server needs to process it. Session data is stored externally (in a database or cache like Redis), not in the server's memory.

Advantages of stateless:

  • Any server can handle any request (easy to scale)
  • Servers can crash without losing user data
  • Load balancer can send requests anywhere
  • Adding new servers is trivial

This is why stateless design is a core principle of scalable systems. See Scaling Fundamentals for how this enables horizontal scaling.

What a Web Server Actually Does

When people say "web server," they might mean two different things:

1. HTTP Server Software

Software that listens on a port (usually 80 or 443), accepts HTTP connections, and sends back responses. The most common HTTP servers:

ServerMarket Share (2026)Known For
Nginx~34%High performance, reverse proxy, load balancing
Apache~28%Oldest major web server, very configurable
Cloudflare~22%CDN + edge computing
Node.js (Express)~5%JavaScript, event-driven

2. The Application Server

The code that actually processes requests — your Python/Node/Java/Go application that contains business logic:

In a typical production setup, Nginx sits in front of your application server. Nginx handles the raw HTTP connections, TLS termination, and static files. Your application server handles the business logic. See Nginx Config for how to set this up.

REST APIs — How Clients Talk to Servers

When the client is a browser or mobile app and the server is a backend API, they communicate using REST (Representational State Transfer). REST is a set of conventions for designing HTTP APIs.

REST Conventions

GET    /users          → List all users
GET    /users/123      → Get user with ID 123
POST   /users          → Create a new user
PUT    /users/123      → Replace user 123 entirely
PATCH  /users/123      → Update some fields of user 123
DELETE /users/123      → Delete user 123

A Complete Request/Response Example

Request (client sends this):

http
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

{
  "name": "Alice Johnson",
  "email": "alice@example.com"
}

Response (server sends this):

http
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/users/456

{
  "id": 456,
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "created_at": "2026-03-25T10:30:00Z"
}

For a complete guide to REST API design, see REST Best Practices. For alternatives to REST, see GraphQL vs REST and gRPC Internals.

Request-Response vs Push Models

Client-server is not always request-response. There are other patterns:

PatternDirectionUse Case
Request-ResponseClient → Server → ClientLoading pages, API calls
Long PollingClient → Server (waits) → ClientEmail checking, basic notifications
WebSocketBidirectionalChat apps, gaming, live collaboration
Server-Sent EventsServer → Client onlyLive dashboards, news feeds

For details on these patterns, see Event-Driven APIs and WebSockets.

Real-World Architecture Example: A Simple Blog

Let us walk through a concrete example. You are building a blog. Here is how the architecture evolves:

Version 1: Simple Static Files

Just HTML, CSS, and JavaScript files served by Nginx. No database. No backend. Works for a personal portfolio.

Version 2: Dynamic Content with a Database

Now you have a server that fetches blog posts from a database and generates HTML. Users can create and edit posts through an admin panel.

Version 3: Separate Frontend and Backend

The frontend is a React SPA served from a CDN. The backend is a REST API. This is the standard architecture for most web applications today.

Common Mistakes Beginners Make

  1. Putting business logic in the client — Never trust the client. It can be manipulated. Validate everything on the server.

  2. Making the client talk directly to the database — This is a massive security hole. Always put a server in between.

  3. Storing session state in the server's memory — This prevents horizontal scaling. Use Redis or a database for sessions.

  4. Not understanding that the client and server are separate programs — They run on different machines, have different clocks, and the network between them is unreliable.

  5. Thinking "server" means a physical machine — A server is software. One physical machine can run dozens of server programs.

Summary

ConceptKey Takeaway
Client-ServerOne program requests, another responds
MonolithEverything on one machine (simple but limited)
Two-TierClient + Database (security issues)
Three-TierClient + Application Server + Database (modern standard)
N-TierMany specialized services (microservices)
Thin ClientServer does the work, client just displays
Thick ClientClient does significant processing
StatefulServer remembers between requests (hard to scale)
StatelessEvery request is self-contained (easy to scale)
RESTConvention for designing HTTP APIs

What to Learn Next

"What I cannot create, I do not understand." — Richard Feynman