Art of Codeartofcode
LLeeaarrnniinngg
BBlloogg
TToooollss
GGaammeess AArreennaa
JJoobbss
LLiivvee CCoouurrsseess

Courses

  • System DesignHigh-level system design, one everyday scene at a time: 30 concepts and 15 interview rounds.712 lessons
All coursesTutorialsMy Learning

Categories

  • 01AI & Tools
  • 02Tutorials
  • 03Engineering
  • 04Reviews
  • 05Build Logs
  • 06Tales of Misfits
  • 07Opinion
  • 08Career
  • 09News

Read & write

All storiesEvery post, newest first.Write for usPublish your stories and earn from what you write.Writer leaderboardsWho is writing the most read posts.

Categories

  • PDF Tools25
  • Development09
  • Utilities10
  • Design04
  • Converters04
  • Generators02

Featured

JSON FormatterFormat, validate and minify JSON.Regex TesterTest patterns against live text.Merge PDFCombine PDFs in your browser.JWT DecoderRead a token’s header and claims.Password GeneratorStrong passwords, generated locally.Gradient GeneratorBuild CSS gradients visually.
All 53 tools

Play a round

DevdleOne developer word a day, six guesses.Python RushClassic snake, with coding icons to eat.Blink or BreakA quick test of your reflexes.
Games Arena

Learn with us

Live CoursesInstructor-led courses. Join a waitlist and be first in when one starts.LearningStructured programming courses with AI assistance and certificates.

System Design

3. Client and Server

Lesson 16 of 18

3. Client and Server

1
The picture to keep in your head
2
3.1 What exactly are a client and a server?
3
3.2 What's a request and a response?
4
3.3 What happens when you type a URL and press Enter?
5
3.4 What do GET, POST, PUT, PATCH and DELETE mean?
6
3.5 What do status codes tell you?
7
3.6 What goes in the headers and what goes in the body?
8
3.7 What's the difference between TCP and UDP?
9
3.8 How does HTTPS keep the conversation private?
10
3.9 Why do keep-alive, HTTP/2 and HTTP/3 make things faster?
11
3.10 What does "stateless" mean, and why do we want it?
12
3.11 How do cookies, sessions and tokens remember who you are?
13
Memory card and where the analogy breaks
14
Practice: five levels
15
Interview questions
16
Solutions
17
Sources
18
Code lab
3. Client and Server

Solutions

3 min read+10 XP

Solutions

Level 1

reveal

Level 2

reveal

Level 3

reveal

Level 4

reveal

Level 5 (sketch)

reveal

No tracks available

Lofi Player

artofcode

artofcode.in

The den of devs.

Stories, tools, games, and gear for developers.

Read the StoriesEExxpplloorree TToooollss
Art of Codeartofcode

Platform

  • BBlloogg
  • TToooollss
  • GGaammeess AArreennaa
  • CCoouurrsseess
  • LLeeaarrnniinngg
  • CCaammppuuss

Company

  • AAbboouutt UUss
  • JJoobbss && IInntteerrnnsshhiippss
  • CCoonnttaacctt

Legal

  • TTeerrmmss ooff SSeerrvviiccee
  • PPrriivvaaccyy PPoolliiccyy
  • RReeffuunndd PPoolliiccyy

Copyright © 2026 artofcode.in, All Rights Reserved.

IST·--:--

1Show the Level 1 solution
2**A.**
31. `GET /users/{id}/orders` → **200**.
42. `POST /orders` → **201** Created.
53. `PUT /users/{id}/address` → **200** (or **204** with no body).
64. `DELETE /wishlist/items/{id}` → **204** (or 200).
75. `PATCH /cart/items/{id}` with the new quantity → **200**.
8
9**B.**
101. **400** Bad Request.
112. **401** Unauthorized.
123. **403** Forbidden. (Some APIs return **404** here on purpose, so they don't even reveal that the order exists.)
134. **429** Too Many Requests, ideally with `Retry-After`.
145. **504** Gateway Timeout.
1Show the Level 2 solution
21. TCP handshake (1 round trip) + TLS 1.3 (1) + request and response (1) = 3 × 200 ms = **600 ms**.
32. Just the request and response: **200 ms**.
43. QUIC handles transport and TLS together (1) + request and response (1) = **400 ms**.
54. New connection each time: 20 × 600 = **12 seconds**. Reused: 600 + 19 × 200 = **4.4 seconds**.
65. At 20 ms: new connections 20 × 60 = **1.2 seconds**; reused 60 + 19 × 20 = **0.44 seconds**.
7
8The lesson: **reuse connections** and **move servers (or a CDN) closer**. Both together turn 12 seconds into under half a second. Making the calls in parallel instead of one after another helps even more.
1Show the Level 3 solution
2Tested solution (Python 3, standard library):
3
4```python
5import json
6from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
7
8BOOKS = {"42": {"id": "42", "title": "Designing Systems", "price": 499}}
9CART = []
10
11
12class BookstoreHandler(BaseHTTPRequestHandler):
13    def _send(self, status, body=None):
14        data = b"" if body is None else json.dumps(body).encode()
15        self.send_response(status)
16        self.send_header("Content-Type", "application/json")
17        self.send_header("Content-Length", str(len(data)))
18        self.end_headers()
19        self.wfile.write(data)
20
21    def do_GET(self):
22        if self.path.startswith("/books/"):
23            book = BOOKS.get(self.path.rsplit("/", 1)[1])
24            return self._send(200, book) if book else self._send(404, {"error": "no such book"})
25        self._send(404, {"error": "not found"})
26
27    def do_POST(self):
28        if self.path != "/cart":
29            return self._send(405, {"error": "method not allowed"})
30        length = int(self.headers.get("Content-Length", 0))
31        try:
32            item = json.loads(self.rfile.read(length) or b"{}")
33        except json.JSONDecodeError:
34            return self._send(400, {"error": "body is not valid JSON"})
35        if item.get("book_id") not in BOOKS:
36            return self._send(400, {"error": "unknown book_id"})
37        CART.append(item)
38        self._send(201, {"cart_size": len(CART)})
39
40    def do_DELETE(self):
41        self._send(405, {"error": "method not allowed"})
42```
43
44All checks pass, including the client calls. The full file is in `code/ch03_client_server.py`.
1Show the Level 4 solution
2**The bug:** each server keeps sessions **in its own memory**. The session exists only on the server that handled the login.
3
41. Login lands on **server A**. A stores the session and the browser gets the session ID in a cookie.
52. Click 1: the load balancer sends it to **server B**. B has never seen that ID → "please log in again".
63. Click 2 goes to **A** → works.
74. Click 3 → **B** → logged out. Click 4 → **A** → works.
8
9The tested demo shows exactly this: `[None, 'asha', None, 'asha']`.
10
11**Fix 1: a shared session store.** All servers read and write sessions in one place, like Redis:
12
13```python
14class AppServer:
15    def __init__(self, store):
16        self.store = store              # shared by every server
17
18    def login(self, user):
19        sid = secrets.token_hex(8)
20        self.store.data[sid] = user
21        return sid
22
23    def whoami(self, sid):
24        return self.store.data.get(sid)
25```
26
27**Fix 2: signed tokens.** Put the user's identity in a signed, short-lived token. Any server checks the signature; no shared store needed for each request.
28
29(**Sticky sessions** on the load balancer would hide the symptom, but a server restart still logs everyone on it out, and load can't be spread evenly. Treat it as a stopgap.)
1Show the Level 5 (sketch) solution
21. **API:** `GET /books?query=&cursor=` (200), `GET /books/{id}` (200), `GET /cart` (200), `POST /cart/items` (201), `PATCH /cart/items/{id}` (200), `DELETE /cart/items/{id}` (204), `POST /orders` (201, with an idempotency key).
32. **Login:** short-lived **access tokens** (minutes) checked by every service by signature, plus a revocable **refresh token**. On the **web**, keep them in `HttpOnly`, `Secure`, `SameSite` cookies. On **mobile**, keep them in the platform's secure storage. Refresh tokens are recorded server-side.
43. **Log out everywhere:** on password change, revoke all of the user's refresh tokens. Access tokens die within minutes; for instant effect, add the user's current token IDs to a short deny-list until they expire.
54. **Latency:** serve static content and images from a **CDN** (Chapter 26); **reuse connections** and use HTTP/2 or HTTP/3; deploy servers in a region near users.
65. **Retries:** safe to retry **GET, PUT, DELETE**, and PATCH calls written as "set" operations. **Never blindly retry POST /orders** or payments; retry only with the same **idempotency key** so the server can spot the repeat (Chapter 24).