Foundations

Client-Server Architecture: REST, Statelessness, and HTTP Methods

Understand the client-server model, REST principles, HTTP methods, idempotency, and how to design clean APIs.

12 min readclient-serverRESTHTTPAPI designidempotency

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

ConstraintWhat It MeansWhy It Matters
Client-ServerSeparation of concernsIndependent evolution of client and server
StatelessEach request is self-containedScalability, reliability, visibility
CacheableResponses must declare cacheabilityPerformance through caching
Uniform InterfaceConsistent API designSimplicity, decoupling
Layered SystemClient doesn't know about intermediariesLoad balancers, proxies, gateways transparent
Code on Demand (optional)Server can send executable codeExtensibility (rarely used)

The Uniform Interface — 4 Sub-Constraints

  1. Resource Identification — Every resource has a URI (/users/123)
  2. Resource Manipulation Through Representations — Clients modify resources via representations (JSON, XML)
  3. Self-Descriptive Messages — Each message contains enough info to process it (Content-Type, HTTP method)
  4. 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.

MethodSafeIdempotentDescription
GET✅ Yes✅ YesRetrieve a resource
POST❌ No❌ NoCreate a resource
PUT❌ No✅ YesReplace a resource entirely
PATCH❌ No❌ No (usually)Partially update a resource
DELETE❌ No✅ YesDelete 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

CodeMeaningWhen to Use
200OKSuccessful GET, PUT, PATCH
201CreatedSuccessful POST (resource created)
204No ContentSuccessful DELETE (no response body)

4xx — Client Error

CodeMeaningWhen to Use
400Bad RequestInvalid input, malformed request
401UnauthorizedMissing or invalid authentication
403ForbiddenAuthenticated but not authorized
404Not FoundResource doesn't exist
409ConflictRequest conflicts with current state
429Too Many RequestsRate limit exceeded

5xx — Server Error

CodeMeaningWhen to Use
500Internal Server ErrorUnexpected server failure
502Bad GatewayUpstream server returned invalid response
503Service UnavailableServer is temporarily down (maintenance, overload)

RESTful Resource Naming

Good API design starts with good resource naming.

Rules of Thumb

  • Use nouns, not verbs: GET /users not GET /getUsers
  • Use plural nouns: /users not /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/users or via header Accept: 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

  1. Stateless vs stateful — Stateless scales better; stateful has lower latency per request
  2. REST constraints — Especially stateless, uniform interface, and cacheable
  3. HTTP method semantics — Safe vs idempotent, know the table
  4. Status codes — 200, 201, 400, 401, 403, 404, 500, 503
  5. Resource naming — Nouns, plural, nested for relationships