Client-Server Architecture: REST, Statelessness, and HTTP Methods
Understand the client-server model, REST principles, HTTP methods, idempotency, and how to design clean APIs.
The Client-Server Model
At its core, almost every system you'll design follows the client-server pattern. It's simple:
- Client — Makes requests (browser, mobile app, another service)
- Server — Processes requests and returns responses
- Network — The medium between them
┌──────────┐ Request ┌──────────┐
│ Client │ ───────────────> │ Server │
│ │ <─────────────── │ │
│ │ Response │ │
└──────────┘ └──────────┘
The key insight is separation of concerns: the client doesn't care how the server processes the request, and the server doesn't care who the client is. They communicate through a well-defined contract (the API).
Evolution: The model has evolved from 2-tier (client → database) to 3-tier (client → application server → database) to n-tier (microservices). But the fundamental client-server relationship remains.
Stateless vs Stateful Protocols
Stateless: Every Request Stands Alone
In a stateless protocol, each request contains all the information the server needs. The server doesn't remember anything about previous requests.
HTTP is stateless. Each HTTP request is independent.
Request 1: GET /users/123 → Server responds with user 123
Request 2: GET /users/123/posts → Server responds with posts (must re-identify user 123)
Advantages:
- Servers can scale horizontally — any server can handle any request
- Failed requests don't corrupt server state
- Simple to cache and retry
Stateful: The Server Remembers
In a stateful protocol, the server maintains session state between requests.
TCP is stateful. Once the connection is established, the server remembers the connection state.
Advantages:
- Faster subsequent requests (no need to re-authenticate, re-establish context)
- Can maintain conversational interactions
The trade-off: Stateful servers are harder to scale because requests from the same client must go to the same server (sticky sessions / session affinity).
Interview answer: "REST APIs should be stateless. Session state belongs on the client (JWT token, cookies). Server-side session storage breaks horizontal scaling and creates a single point of failure."
REST — Representational State Transfer
REST is an architectural style, not a protocol or standard. It defines constraints for how clients and servers should communicate.
The 6 REST Constraints
| Constraint | What It Means | Why It Matters |
|---|---|---|
| Client-Server | Separation of concerns | Independent evolution of client and server |
| Stateless | Each request is self-contained | Scalability, reliability, visibility |
| Cacheable | Responses must declare cacheability | Performance through caching |
| Uniform Interface | Consistent API design | Simplicity, decoupling |
| Layered System | Client doesn't know about intermediaries | Load balancers, proxies, gateways transparent |
| Code on Demand (optional) | Server can send executable code | Extensibility (rarely used) |
The Uniform Interface — 4 Sub-Constraints
- Resource Identification — Every resource has a URI (
/users/123) - Resource Manipulation Through Representations — Clients modify resources via representations (JSON, XML)
- Self-Descriptive Messages — Each message contains enough info to process it (Content-Type, HTTP method)
- HATEOAS — Hypermedia as the Engine of Application State (responses include links to related actions)
HTTP Methods and Their Semantics
RESTful APIs use HTTP methods to express intent. Understanding their semantics is critical.
| Method | Safe | Idempotent | Description |
|---|---|---|---|
| GET | ✅ Yes | ✅ Yes | Retrieve a resource |
| POST | ❌ No | ❌ No | Create a resource |
| PUT | ❌ No | ✅ Yes | Replace a resource entirely |
| PATCH | ❌ No | ❌ No (usually) | Partially update a resource |
| DELETE | ❌ No | ✅ Yes | Delete a resource |
What "Safe" Means
A safe method doesn't modify server state. GET should never change anything. If you call GET /users/123 a million times, the user should remain unchanged.
What "Idempotent" Means
An idempotent method produces the same result no matter how many times you call it.
PUT /users/123 { "name": "Alice" }
PUT /users/123 { "name": "Alice" } ← Same result
PUT /users/123 { "name": "Alice" } ← Same result
But POST is not idempotent:
POST /users { "name": "Alice" } → Creates user with ID 101
POST /users { "name": "Alice" } → Creates user with ID 102 ← Different!
Interview trap: "Is PATCH idempotent?" — The spec says it's not guaranteed to be idempotent. It depends on the implementation. If PATCH applies a delta (e.g., { "op": "add", "field": "score", "value": 10 }), calling it twice gives a different result than calling it once.
HTTP Status Codes You Must Know
Don't memorize all of them. Know these categories and the most important ones:
2xx — Success
| Code | Meaning | When to Use |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST (resource created) |
| 204 | No Content | Successful DELETE (no response body) |
4xx — Client Error
| Code | Meaning | When to Use |
|---|---|---|
| 400 | Bad Request | Invalid input, malformed request |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Request conflicts with current state |
| 429 | Too Many Requests | Rate limit exceeded |
5xx — Server Error
| Code | Meaning | When to Use |
|---|---|---|
| 500 | Internal Server Error | Unexpected server failure |
| 502 | Bad Gateway | Upstream server returned invalid response |
| 503 | Service Unavailable | Server is temporarily down (maintenance, overload) |
RESTful Resource Naming
Good API design starts with good resource naming.
Rules of Thumb
- Use nouns, not verbs:
GET /usersnotGET /getUsers - Use plural nouns:
/usersnot/user - Use nested resources for relationships:
/users/123/posts - Use query parameters for filtering, sorting, pagination:
/users?role=admin&sort=name&limit=20 - Version your API:
/api/v1/usersor via headerAccept: application/vnd.myapi.v1+json
Example: E-Commerce API
GET /api/v1/products → List all products
GET /api/v1/products/42 → Get product 42
POST /api/v1/products → Create a product
PUT /api/v1/products/42 → Replace product 42
PATCH /api/v1/products/42 → Update product 42 (partial)
DELETE /api/v1/products/42 → Delete product 42
GET /api/v1/products/42/reviews → List reviews for product 42
POST /api/v1/products/42/reviews → Add a review
Design tip: Think of your API as a resource tree. Each URL path should represent a specific resource or collection. If you find yourself creating verb-based endpoints (/users/activate, /orders/cancel), reconsider your resource model.
What to Remember for Interviews
- Stateless vs stateful — Stateless scales better; stateful has lower latency per request
- REST constraints — Especially stateless, uniform interface, and cacheable
- HTTP method semantics — Safe vs idempotent, know the table
- Status codes — 200, 201, 400, 401, 403, 404, 500, 503
- Resource naming — Nouns, plural, nested for relationships