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).