Client-Server Architecture

0/4 in this phase0/45 across the roadmap

📖 Concept

Understanding the client-server model is the first step in system design. Every modern application, from a simple website to Netflix, is built on this fundamental pattern.

🏠 Real-world Analogy

Think of a restaurant: the customer (client) places an order, the waiter (network) carries it to the kitchen (server), and the chef (backend logic) prepares the food (response). The customer never goes into the kitchen — they only interact through the waiter.

How It Works

Component Role Example
Client Sends requests, renders UI Browser, mobile app, CLI
Server Processes requests, manages data Web server, API server
Protocol Rules for communication HTTP, WebSocket, gRPC
Database Persistent storage PostgreSQL, MongoDB

Key Concepts

  • Request-Response Cycle: The client sends a request (e.g., GET /users), the server processes it, queries the database if needed, and returns a response (e.g., JSON with user data).
  • Stateless vs Stateful Servers: In a stateless architecture, the server doesn't remember previous requests — each request contains all necessary information (e.g., JWT tokens). In a stateful architecture, the server maintains session state (e.g., sticky sessions). Stateless is preferred in modern distributed systems because it allows horizontal scaling.
  • Tiers: Applications can be single-tier (everything on the client, like a desktop app), two-tier (client + database), three-tier (client + server + database), or n-tier (multiple layers like load balancer, application server, cache, database, CDN).

Why This Matters in System Design Interviews

Every system design question starts with a client making requests to a server. Understanding this model helps you draw the initial architecture diagram and reason about where to add components like load balancers, caches, and message queues.

Pro tip: Always start your system design interview by drawing a simple client → server → database diagram, then progressively add complexity.

💻 Code Example

codeTap to expand ⛶
1// ============================================
2// Client-Server Architecture — Conceptual Demo
3// ============================================
4
5// ---------- SERVER SIDE (Node.js + Express) ----------
6
7const express = require('express');
8const app = express();
9
10// ❌ BAD: Stateful server — stores session in memory
11// This breaks when you add a second server behind a load balancer
12let sessionStore = {}; // In-memory session — lost on restart!
13
14app.post('/login-bad', (req, res) => {
15 const { userId } = req.body;
16 const sessionId = generateSessionId();
17 sessionStore[sessionId] = { userId, loggedInAt: Date.now() };
18 res.json({ sessionId });
19});
20
21app.get('/profile-bad', (req, res) => {
22 const session = sessionStore[req.headers['session-id']];
23 if (!session) return res.status(401).json({ error: 'Not authenticated' });
24 res.json({ userId: session.userId });
25});
26
27// ✅ GOOD: Stateless server — uses JWT tokens
28// Works perfectly with multiple servers behind a load balancer
29const jwt = require('jsonwebtoken');
30const SECRET = process.env.JWT_SECRET || 'your-secret-key';
31
32app.post('/login', (req, res) => {
33 const { userId } = req.body;
34 // Token contains all session info — server doesn't need to remember anything
35 const token = jwt.sign({ userId, role: 'user' }, SECRET, { expiresIn: '24h' });
36 res.json({ token });
37});
38
39app.get('/profile', authenticateToken, (req, res) => {
40 // User info comes FROM the token, not from server memory
41 res.json({ userId: req.user.userId, role: req.user.role });
42});
43
44function authenticateToken(req, res, next) {
45 const authHeader = req.headers['authorization'];
46 const token = authHeader && authHeader.split(' ')[1]; // "Bearer <token>"
47
48 if (!token) return res.status(401).json({ error: 'Token required' });
49
50 jwt.verify(token, SECRET, (err, user) => {
51 if (err) return res.status(403).json({ error: 'Invalid token' });
52 req.user = user;
53 next();
54 });
55}
56
57// ---------- Three-Tier Architecture Example ----------
58
59// Tier 1: Client (browser) — sends HTTP requests
60// Tier 2: Application Server — handles business logic
61// Tier 3: Database — persists data
62
63// This server IS Tier 2
64app.get('/api/users', async (req, res) => {
65 try {
66 // Tier 2 talks to Tier 3 (database)
67 const users = await database.query('SELECT id, name, email FROM users LIMIT 100');
68 // Tier 2 returns response to Tier 1 (client)
69 res.json({ users, count: users.length });
70 } catch (error) {
71 res.status(500).json({ error: 'Internal server error' });
72 }
73});
74
75app.listen(3000, () => console.log('Server running on port 3000'));
76
77function generateSessionId() {
78 return Math.random().toString(36).substring(2, 15);
79}

🏋️ Practice Exercise

  1. Draw the Architecture: Sketch a three-tier architecture for an e-commerce site. Label each tier and the communication protocols between them.

  2. Stateless Refactor: Given a server that stores user preferences in memory, refactor it to be stateless by storing preferences in a database and using tokens for authentication.

  3. Request Flow Trace: Trace the complete request flow when a user opens "amazon.com" — from DNS resolution to the final rendered page. Include every server involved.

  4. Multi-Tier Design: Design a 4-tier architecture for a video streaming platform (client, CDN, application server, database). Explain why each tier exists.

  5. Failure Scenario: Your stateful server crashes and restarts. What happens to all active users? Now explain how a stateless design handles the same crash.

  6. Scaling Exercise: You have one server handling 1,000 requests/second. Traffic grows to 10,000 req/s. Explain why stateless architecture makes scaling easier than stateful.

⚠️ Common Mistakes

  • Designing stateful servers in a distributed system — this causes session loss when servers crash or when load balancers route requests to different servers. Always prefer stateless designs with external session stores.

  • Confusing client-server with peer-to-peer — in client-server, roles are fixed; in P2P (like BitTorrent), every node is both client and server. Most interview questions assume client-server.

  • Forgetting about the network — beginners often treat server calls as instant. In reality, network latency (50-200ms), packet loss, and timeouts must be accounted for in every design.

  • Putting business logic on the client — this creates security vulnerabilities (users can modify client code) and makes updates harder. Keep validation and critical logic server-side.

💼 Interview Questions

🎤 Mock Interview

Practice a live interview for Client-Server Architecture