Client-Server Architecture
📖 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
1// ============================================2// Client-Server Architecture — Conceptual Demo3// ============================================45// ---------- SERVER SIDE (Node.js + Express) ----------67const express = require('express');8const app = express();910// ❌ BAD: Stateful server — stores session in memory11// This breaks when you add a second server behind a load balancer12let sessionStore = {}; // In-memory session — lost on restart!1314app.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});2021app.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});2627// ✅ GOOD: Stateless server — uses JWT tokens28// Works perfectly with multiple servers behind a load balancer29const jwt = require('jsonwebtoken');30const SECRET = process.env.JWT_SECRET || 'your-secret-key';3132app.post('/login', (req, res) => {33 const { userId } = req.body;34 // Token contains all session info — server doesn't need to remember anything35 const token = jwt.sign({ userId, role: 'user' }, SECRET, { expiresIn: '24h' });36 res.json({ token });37});3839app.get('/profile', authenticateToken, (req, res) => {40 // User info comes FROM the token, not from server memory41 res.json({ userId: req.user.userId, role: req.user.role });42});4344function authenticateToken(req, res, next) {45 const authHeader = req.headers['authorization'];46 const token = authHeader && authHeader.split(' ')[1]; // "Bearer <token>"4748 if (!token) return res.status(401).json({ error: 'Token required' });4950 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}5657// ---------- Three-Tier Architecture Example ----------5859// Tier 1: Client (browser) — sends HTTP requests60// Tier 2: Application Server — handles business logic61// Tier 3: Database — persists data6263// This server IS Tier 264app.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});7475app.listen(3000, () => console.log('Server running on port 3000'));7677function generateSessionId() {78 return Math.random().toString(36).substring(2, 15);79}
🏋️ Practice Exercise
Draw the Architecture: Sketch a three-tier architecture for an e-commerce site. Label each tier and the communication protocols between them.
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.
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.
Multi-Tier Design: Design a 4-tier architecture for a video streaming platform (client, CDN, application server, database). Explain why each tier exists.
Failure Scenario: Your stateful server crashes and restarts. What happens to all active users? Now explain how a stateless design handles the same crash.
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