Client-Server Architecture in System Design
Client-server architecture is a model in which clients request services or data and servers provide them over a network. Every time you open a website, check email, stream a video or use a banking app, a client on your device is talking to servers somewhere else. It is the most widely used architecture on the internet and the starting point for nearly every system design.
This tutorial explains the parts of a client-server system, how a request travels from client to server and back, the 1-tier, 2-tier, 3-tier and n-tier variations, thin and thick clients, real-world examples, and how to build a simple client and server in Java. It also covers how client-server systems scale, their advantages and drawbacks, and how they compare with peer-to-peer systems.
1. What Is Client-Server Architecture?
Think of a restaurant. You (the client) look at the menu and place an order. The kitchen (the server) prepares the food and sends it back. You never walk into the kitchen, and the kitchen never decides what you eat. The waiter carrying orders back and forth is like the network, and the menu, with its agreed list of dishes, is like the protocol.
In computing, client-server architecture divides work between two roles:
- The client starts the conversation. It sends a request and waits for a response.
- The server waits for requests, processes them, and sends back responses. One server usually serves many clients at the same time.
The server owns the shared resources: the data, business rules and heavy processing. Clients focus on interacting with users. This central ownership is what makes the model easy to secure, update and manage.
2. Key Components
| Component | Role | Examples |
|---|---|---|
| Client | Sends requests, shows results to the user | Web browsers, mobile apps, desktop apps, IoT devices, other services |
| Server | Listens for requests, runs logic, returns responses | Web servers, application servers, database servers, mail servers |
| Network | Carries messages between client and server | The internet, an office LAN, a mobile network |
| Protocol | Agreed rules for the message format and order | HTTP/HTTPS, WebSocket, gRPC, SMTP, DNS, database wire protocols |
| Data store | Keeps persistent data for the server | MySQL, PostgreSQL, MongoDB, object storage |
Note that "client" and "server" are roles, not types of hardware. A server process can run on a laptop, and a back-end service acts as a client when it calls another service or a database.
3. How a Client-Server Request Works
Let us follow what happens when a user opens https://shop.example.com/products in a browser:
- Find the server: the browser asks DNS to translate the domain name into an IP address (often answered from a cache).
- Get the address: DNS returns the IP address of the server or its load balancer.
- Connect: the browser opens a TCP connection and performs a TLS handshake so the conversation is encrypted.
- Send the request: an HTTP request such as
GET /products, with headers like cookies and accepted formats. - Process: the server checks who the user is, runs business logic, and reads from the database or cache.
- Respond: the server returns a status code (such as
200 OK) and a body, such as HTML or JSON. - Display: the browser renders the page, and may send more requests for images, scripts and styles.
This request-response pattern is the heart of client-server systems. When the server needs to push updates without being asked, such as chat messages, techniques like WebSockets extend the model.
4. Types of Client-Server Architecture
Client-server systems are often described by how many tiers (separately running layers) they have.
1-tier architecture
The user interface, business logic and data all live in one application on one machine, such as a desktop spreadsheet that saves to a local file. Simple, but there is no sharing between users.
2-tier architecture
The client talks directly to the database server. The client application contains the user interface and most of the business logic. This was common for internal office applications. It is fast for a small number of users, but every client needs database access and credentials, business rules are spread across many installed clients, and it does not scale to large numbers of users.
3-tier architecture
A middle application tier sits between clients and the database. This is the standard model for web applications:
- Presentation tier: what the user sees and interacts with.
- Application (logic) tier: validates input, applies business rules, coordinates work and exposes APIs.
- Data tier: stores and retrieves data.
Because each tier is separate, you can scale, update and secure them independently. The database is hidden from the internet, and business rules live in one place.
N-tier architecture
Large systems add more layers: a CDN, load balancers, an API gateway, caching tiers, separate services, message queues and search engines. Each extra tier solves a specific problem, such as speed, scale or security, at the cost of more moving parts. Microservices can be seen as an n-tier design split further by business capability.
| Model | Structure | Strengths | Weaknesses | Typical use |
|---|---|---|---|---|
| 1-tier | Everything on one machine | Simplest | No sharing or central control | Standalone desktop tools |
| 2-tier | Client ↔ database | Fast, simple for small teams | Weak security, poor scaling, logic in every client | Small internal apps |
| 3-tier | Client ↔ app server ↔ database | Secure, maintainable, scalable | An extra network hop | Most web and mobile applications |
| N-tier | Many specialised layers | Highly scalable and flexible | More complex to build and operate | Large-scale platforms |
5. Thin Clients vs Thick Clients
Client-server systems also differ in how much work the client does:
| Aspect | Thin client | Thick (fat) client |
|---|---|---|
| Where logic runs | Mostly on the server | Much of it on the client device |
| Device requirements | Low; little processing or storage | Higher; needs CPU, memory and storage |
| Updates | Change the server once, everyone gets it | Each client must be updated |
| Offline use | Usually not possible | Often possible, syncs later |
| Network dependency | High, every action needs the server | Lower, many actions work locally |
| Examples | Server-rendered web pages, remote desktops | Video games, IDEs, offline-capable mobile apps |
Modern single-page web apps and mobile apps sit in between: they run a lot of interface logic on the device but keep business rules and data on the server.
6. Real-World Examples
- The web: browsers (clients) request pages and APIs from web servers using HTTP.
- Email: mail apps send messages to a mail server with SMTP and fetch them with IMAP.
- Databases: your Spring Boot application is a client of the MySQL or PostgreSQL server.
- DNS: every device is a DNS client that asks DNS servers to resolve domain names.
- Online banking: the banking app sends requests to the bank's servers, which own the accounts and enforce every rule.
- Multiplayer games: game clients send player actions to an authoritative game server that decides what really happened, which prevents cheating.
- File storage: cloud drive apps upload to and download from storage servers.
7. Building a Simple Client and Server in Java
At the lowest level, a client and server talk over a socket, an endpoint for a network connection identified by an IP address and port. The server below listens on port 5000 and understands two text commands. It uses virtual threads (Java 21) so each connected client is served on its own lightweight thread.
package com.javabytechie.clientserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TimeServer {
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(5000);
ExecutorService workers = Executors.newVirtualThreadPerTaskExecutor()) {
System.out.println("Server listening on port 5000");
while (true) {
Socket client = server.accept(); // wait for the next client
workers.submit(() -> handle(client)); // serve it on its own virtual thread
}
}
}
private static void handle(Socket socket) {
System.out.println("Client connected: " + socket.getRemoteSocketAddress());
try (socket;
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
PrintWriter out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {
String request;
while ((request = in.readLine()) != null) {
switch (request.trim().toUpperCase()) {
case "TIME" -> out.println("OK " + LocalTime.now().withNano(0));
case "BYE" -> { out.println("OK goodbye"); return; }
default -> out.println("ERROR unknown command '" + request + "'");
}
}
} catch (IOException e) {
System.out.println("Connection problem: " + e.getMessage());
} finally {
System.out.println("Client disconnected");
}
}
}
package com.javabytechie.clientserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class TimeClient {
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket("localhost", 5000);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
PrintWriter out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {
for (String command : List.of("TIME", "WEATHER", "BYE")) {
out.println(command); // send a request
String response = in.readLine(); // wait for the server's response
System.out.println("Sent: " + command + " -> Received: " + response);
}
}
}
}
Start TimeServer first, then run TimeClient in another terminal:
Sent: TIME -> Received: OK 05:22:47
Sent: WEATHER -> Received: ERROR unknown command 'WEATHER'
Sent: BYE -> Received: OK goodbye
Server listening on port 5000
Client connected: /127.0.0.1:50358
Client disconnected
This tiny program shows every element of the model: the server listens and owns the logic, the client starts the conversation, and both follow a simple protocol (one text line per request and per response). HTTP, SMTP and database protocols are just richer versions of the same idea.
8. A Client-Server Example with Spring Boot REST
In real applications you rarely write raw sockets. HTTP and JSON are the common protocol, and Spring Boot handles the networking. Here is a small product API (the server) and a Java client calling it:
package com.javabytechie.clientserver;
import java.math.BigDecimal;
import java.util.Map;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/products")
public class ProductController {
public record Product(long id, String name, BigDecimal price) { }
private final Map<Long, Product> catalogue = Map.of(
1L, new Product(1, "Mechanical Keyboard", new BigDecimal("4499.00")),
2L, new Product(2, "USB-C Hub", new BigDecimal("1899.00")));
@GetMapping("/{id}")
public ResponseEntity<Product> findById(@PathVariable long id) {
Product product = catalogue.get(id);
return product != null ? ResponseEntity.ok(product) : ResponseEntity.notFound().build();
}
}
package com.javabytechie.clientserver;
import java.math.BigDecimal;
import org.springframework.web.client.RestClient;
public class ProductClient {
record Product(long id, String name, BigDecimal price) { }
public static void main(String[] args) {
RestClient client = RestClient.create("http://localhost:8080");
Product product = client.get()
.uri("/api/products/{id}", 1)
.retrieve()
.body(Product.class);
System.out.println("Received from server: " + product);
}
}
Received from server: Product[id=1, name=Mechanical Keyboard, price=4499.00]
The server exposes a clear contract (GET /api/products/{id} returning JSON), and any client, whether a browser, a mobile app or another service, can use it without knowing how the server stores its data.
9. Scaling Client-Server Systems
A single server eventually runs out of capacity. Client-server systems grow by adding layers in front of and behind the application:
- Vertical scaling: give the server more CPU and memory. Easy, but limited and creates a single point of failure.
- Horizontal scaling: run several identical servers behind a load balancer. This works best when servers are stateless, keeping session data in a shared store or token instead of server memory.
- Caching: keep frequently requested data in memory (Redis, Memcached) and static files in a CDN.
- Database scaling: add read replicas, then shard when writes or data size outgrow one server.
- Asynchronous processing: move slow work, like sending emails or generating reports, to background workers through a message queue.
10. Advantages of Client-Server Architecture
- Centralised control: data, rules and security policies live on servers you manage.
- Easier security: authentication, authorisation, encryption and auditing are enforced in one place, and sensitive data never needs to live on user devices.
- Simple updates: change the server and every client benefits immediately, especially with thin and web clients.
- Scalability: servers can be scaled up or out independently of clients.
- Data integrity: one authoritative copy of the data avoids conflicting versions.
- Separation of concerns: client and server teams can work independently against an agreed API.
- Client variety: one server can serve web, mobile, desktop and partner clients at the same time.
11. Disadvantages and Challenges
- Single point of failure: if the server, or a component it depends on, goes down, every client is affected. Redundancy and failover are needed.
- Server bottleneck: heavy traffic can overload the server, requiring load balancing and scaling.
- Network dependency: clients cannot work without a connection, and latency affects every interaction.
- Infrastructure cost: servers, databases, bandwidth and operations teams cost money, and costs grow with users.
- Attractive target: a central server holding everyone's data is a prime target for attackers, so it must be well protected.
12. Client-Server vs Peer-to-Peer
| Aspect | Client-Server | Peer-to-Peer (P2P) |
|---|---|---|
| Roles | Fixed: clients request, servers provide | Every peer can both request and provide |
| Control | Centralised | Decentralised |
| Data location | On servers | Spread across peers |
| Scaling | Add server capacity as users grow | Capacity grows naturally as peers join |
| Single point of failure | Yes, unless made redundant | No central point |
| Security and management | Easier, enforced centrally | Harder, peers are untrusted |
| Cost for the provider | Higher infrastructure cost | Lower, users share resources |
| Examples | Websites, banking, email, SaaS products | BitTorrent, blockchain networks, some video-call paths |
Read the Peer-to-Peer Architecture tutorial for a deeper look at the alternative.
13. Best Practices
- Keep servers stateless where possible so they can be scaled horizontally and replaced freely.
- Never trust the client: validate every input and enforce every permission on the server.
- Use HTTPS for all client-server traffic.
- Define clear, versioned APIs so clients and servers can evolve independently.
- Set timeouts and retries with backoff on clients, and make retried operations idempotent.
- Remove single points of failure with multiple server instances, load balancers and database replicas.
- Cache aggressively at the right layers: browser, CDN, application cache.
- Monitor latency, error rates and throughput from both the server side and, where possible, the client side.
14. Summary
- Client-server architecture splits work between clients that request and servers that provide, communicating over a network with an agreed protocol.
- A request typically involves a DNS lookup, a secure connection, a request, server processing and a response.
- Systems range from 1-tier to n-tier; the 3-tier model (presentation, application, data) is the standard for web applications.
- Thin clients rely on the server; thick clients do more work locally.
- The model offers central control, security and easy updates, but needs redundancy and scaling to avoid bottlenecks and single points of failure.
Almost every system you design will be client-server at its core; the art is in how you scale and protect the server side. Open the FAQ tab for answers to common questions about client-server architecture.
Frequently Asked Questions (FAQ)
Q1. What is client-server architecture in simple words?
It is a design where clients, such as browsers or apps, send requests over a network, and servers process those requests and send back responses. The server owns the data and logic, while the client handles what the user sees.
Q2. What are the main components of client-server architecture?
The main components are the client (requests services), the server (provides services), the network (carries messages), the protocol (rules for communication, such as HTTP) and usually a data store used by the server.
Q3. What is the difference between a client and a server?
A client starts communication by sending a request and waits for a response. A server waits for requests, processes them and responds, usually serving many clients at once. These are roles, so the same program can act as a server to some components and a client to others.
Q4. What is 2-tier architecture?
In 2-tier architecture, the client application communicates directly with the database server. The client contains the user interface and most business logic. It is simple for small internal apps but has weaker security and does not scale well.
Q5. What is 3-tier architecture?
3-tier architecture separates a system into a presentation tier (user interface), an application tier (business logic and APIs) and a data tier (database). Clients never access the database directly, which improves security, maintainability and scalability. Most web applications follow this model.
Q6. What is n-tier architecture?
N-tier architecture extends the 3-tier model with additional layers, such as load balancers, API gateways, caches, message queues, search services and CDNs. Each layer handles a specific concern, allowing large systems to scale and evolve, at the cost of more complexity.
Q7. What is the difference between a thin client and a thick client?
A thin client does little processing and relies on the server for most logic, like a server-rendered web page. A thick client does much of the work on the user's device and may work offline, like a video game or desktop IDE.
Q8. Is the World Wide Web a client-server system?
Yes. Web browsers are clients that send HTTP requests, and web servers respond with pages, files and API data. It is the largest client-server system in existence.
Q9. What protocols are used in client-server communication?
Common protocols include HTTP and HTTPS for the web and APIs, WebSocket for real-time communication, gRPC for service-to-service calls, SMTP and IMAP for email, DNS for name resolution, FTP and SFTP for files, and database-specific protocols for MySQL, PostgreSQL and others.
Q10. What are the advantages of client-server architecture?
- Centralised data and control.
- Easier security enforcement.
- Simple updates on the server side.
- Independent scaling of servers.
- One authoritative copy of data.
- Many client types can share one back end.
Q11. What are the disadvantages of client-server architecture?
The server can become a single point of failure and a performance bottleneck, clients depend on network availability, infrastructure costs grow with users, and a central server is an attractive target for attacks. Redundancy, scaling and strong security reduce these risks.
Q12. How does a client find the server?
Usually through DNS: the client looks up the server's domain name and receives an IP address, often of a load balancer. Inside data centres, services may also be found through service discovery systems or configuration.
Q13. How do you scale a client-server application?
Scale the server side by running multiple stateless instances behind a load balancer, adding caching and a CDN, using read replicas and sharding for the database, and moving slow tasks to background workers via message queues.
Q14. Why should servers be stateless?
A stateless server keeps no client-specific data in its own memory between requests, so any instance can handle any request. That makes horizontal scaling, load balancing, deployments and failure recovery much easier. Session data goes into a shared store, a database or a signed token instead.
Q15. What is the difference between client-server and peer-to-peer architecture?
In client-server, roles are fixed and a central server provides resources. In peer-to-peer, every node can both request and provide resources, with no central authority. Client-server is easier to control and secure; peer-to-peer avoids a central point of failure and shares costs among users.
Q16. Can a server also act as a client?
Yes. A back-end service is a server to the browsers calling it, but it acts as a client when it calls a database, a payment provider or another microservice. Client and server describe roles in a specific conversation, not fixed machine types.
Q17. Is microservices architecture a type of client-server architecture?
Yes, in a broad sense. Each microservice is a server exposing an API, and services act as clients of each other. Microservices refine the client-server model by splitting the server side into many small, independently deployable services.
Q18. How does a server handle many clients at the same time?
Servers use concurrency: a thread per request, a pool of worker threads, lightweight virtual threads, or non-blocking event loops. Beyond one machine, a load balancer spreads clients across many server instances.
Q19. What is a socket in client-server communication?
A socket is an endpoint for network communication, identified by an IP address and a port number. A server opens a listening socket on a port, a client connects to it, and both read and write data through the connection. Higher-level protocols like HTTP run on top of sockets.
Q20. Where is client-server architecture used in real life?
Websites and web APIs, email, online banking, e-commerce, streaming services, cloud storage, DNS, database access from applications, and multiplayer games with authoritative servers all use client-server architecture.