7 min read

Q23 — What is REST and what does it actually constrain you to do?


Where does REST come from?

REST is not a standard, a specification, or a framework. It's an architectural style — a set of constraints — described by Roy Fielding in his 2000 PhD dissertation at UC Irvine. Fielding was one of the primary authors of the HTTP specification, and he wrote REST to describe and generalize the architectural properties that made the web scale so well in the 1990s.

This origin matters. REST was not invented and then applied to the web — it was derived from the web. Fielding looked at what the web was doing that allowed it to grow from a few servers to millions while remaining interoperable, and he articulated those principles as a coherent architecture.

Most engineers who say they're building "REST APIs" have not read Fielding's dissertation and are not actually building REST. They're building HTTP APIs with JSON, which is a useful thing to build, but it's not the same thing. Understanding what REST actually requires — and why — matters both for interviews and for making good design decisions.


What are REST's actual constraints?

REST defines six constraints. Violating any of them means your architecture is not REST (though it may still be perfectly good).

1. Client-Server separation

The client and server are separate concerns with a clean interface between them. The server manages data storage and business logic; the client manages user interface and user state. Neither knows or cares about the internals of the other.

Why this matters: you can evolve the client and server independently. A mobile app, a web app, and a third-party integration can all use the same server API without the server knowing or caring what kind of client it's talking to. This was radical in 2000, when many web architectures tightly coupled the server-side template rendering to the server-side data model.

2. Statelessness

Each request from the client must contain all information the server needs to process it. The server stores no session state between requests. If you need authentication, the credentials or token must be in every request. If you need context from a previous request, the client must send that context again.

Why this matters: stateless servers are trivially horizontally scalable. Any request can go to any server — there's no "sticky session" requirement, no need to route a user to the same server that has their session. Load balancers can distribute freely. Server crashes lose no per-user state. This is the single most operationally valuable constraint REST imposes.

The confusion: "stateless" applies to the server, not the application. Your application absolutely has state (user accounts, orders, posts). That state lives in the database. What's stateless is the server's memory between handling individual HTTP requests — it doesn't remember you from request to request.

3. Cacheability

Responses must label themselves as cacheable or non-cacheable. If a response is cacheable, clients and intermediaries (CDNs, proxies) are allowed to reuse it for equivalent future requests.

Why this matters: HTTP's caching infrastructure — Cache-Control, ETag, Last-Modified, Vary — exists to allow responses to be cached at the client, at CDN edge nodes, at reverse proxies, and at every intermediary in between. This dramatically reduces server load and latency. But it only works if the server tells clients what they're allowed to cache and for how long. Designing cacheability into your API responses from the start is a REST constraint that has massive real-world performance implications.

4. Uniform Interface

This is REST's most distinctive and most frequently misunderstood constraint. It has four sub-constraints:

Resources identified by URLs: Everything you can act on is a "resource," and every resource has a stable identifier — its URL. https://api.example.com/users/42 is the resource "user 42." The URL is the identity, not just a lookup path.

Manipulation through representations: Clients don't act on the resource directly — they act on a representation of it (JSON, XML, HTML). The server returns a representation; the client modifies it and sends it back. The server decides how to apply that modification internally.

Self-descriptive messages: Each message carries enough information to describe how to process it. The Content-Type header tells the receiver what format the body is in. The HTTP method tells the receiver what action to take. The URL tells the receiver what resource is being acted on.

HATEOAS (Hypermedia As The Engine Of Application State): This is the constraint almost no one implements, and its absence is why most "REST" APIs aren't truly REST. HATEOAS means responses include links to related actions and resources, so clients discover what they can do next by following links — like a web browser follows hyperlinks — rather than having hard-coded knowledge of the API's URL structure.

A truly RESTful response looks like:

json
{
  "id": 42,
  "name": "Alice",
  "links": {
    "self": "/users/42",
    "posts": "/users/42/posts",
    "follow": "/users/42/follow"
  }
}

The client doesn't need a separate API document to know how to fetch Alice's posts or follow her — the response tells it. This makes clients resilient to URL structure changes: if the server changes /users/42/posts to /posts?author=42, clients following links adapt automatically.

In practice, almost no API implements HATEOAS. This means almost no API is truly RESTful by Fielding's definition. This is fine — HATEOAS adds complexity and most JSON API clients don't benefit from it the way browser-based hyperlink following does. But it's important to know this distinction exists.

5. Layered System

A client doesn't need to know whether it's talking directly to the server or through intermediaries (load balancers, CDN edge nodes, API gateways, authentication proxies). Each layer only knows about the layer immediately adjacent to it. The client sees one interface; what's behind it can be arbitrarily complex.

Why this matters: you can add or remove layers transparently. Insert a CDN in front of your API without changing the client. Add an authentication proxy without changing the backend servers. This composability is fundamental to how the internet's infrastructure works.

6. Code on Demand (optional)

Servers can extend client functionality by sending executable code — like JavaScript that a browser runs. This is the only optional constraint. Most REST APIs don't implement it, and its absence doesn't disqualify an API from being RESTful.


What do HTTP verbs mean in REST?

REST uses HTTP methods to communicate intent:

  • GET — retrieve a resource, read-only, safe (no side effects), idempotent
  • POST — create a new resource or trigger an action, not idempotent
  • PUT — replace a resource entirely, idempotent
  • PATCH — partially update a resource
  • DELETE — remove a resource, idempotent

"Safe" means calling the endpoint doesn't change server state. "Idempotent" means calling it multiple times has the same effect as calling it once. GET is both safe and idempotent. DELETE is idempotent (deleting something twice leaves it deleted) but not safe. POST is neither.

These semantics matter for caching (safe methods can be cached), for retry behavior (idempotent methods can be safely retried on network failure), and for communicating intent to anyone reading the API.


What do people mean when they say "RESTful API" in practice?

In practice, a "RESTful API" typically means:

  • Resources identified by nouns in URLs (/users, /orders, not /getUser, /createOrder)
  • HTTP methods used to indicate operation (GET to read, POST to create, PUT/PATCH to update, DELETE to delete)
  • JSON as the data format
  • Stateless (no server-side session)
  • HTTP status codes used meaningfully (200 OK, 201 Created, 404 Not Found, 400 Bad Request, etc.)

This is the Richardson Maturity Model Level 2 — it's what most production APIs implement. HATEOAS (Level 3) is almost never implemented. The resulting API is not strictly REST by Fielding's definition, but it's a sensible, widely-understood, pragmatic approach to HTTP API design.


The mental model

code
REST = 6 architectural constraints derived from what made the web scale:

  Client-Server → independent evolution of client and server
  Stateless     → horizontal scalability, no sticky sessions, no server-side session state
  Cacheable     → HTTP caching infrastructure: CDN, proxy, client cache
  Uniform Interface:
    URLs as resource identities
    JSON/XML as representations
    Self-descriptive messages (Content-Type, HTTP method)
    HATEOAS → links in responses drive client navigation (rarely implemented)
  Layered System → CDN, proxy, gateway transparent to clients
  Code on Demand → optional, rarely used

What "REST API" means in practice:
  - Noun-based URLs
  - HTTP verbs for intent (GET/POST/PUT/PATCH/DELETE)
  - JSON body
  - Stateless
  - Meaningful HTTP status codes
  → Richardson Level 2 (not true REST, but pragmatic and universally understood)

The most operationally valuable constraint: Statelessness
The most commercially valuable constraint: Cacheability
The most commonly skipped constraint: HATEOAS

REST is valuable not because of the label, but because the constraints — particularly statelessness and cacheability — produce systems that scale horizontally, integrate well with HTTP infrastructure, and are comprehensible to any developer who knows HTTP. That's why the style persisted when more heavyweight alternatives like SOAP and XML-RPC did not.