The REST Constraints
REST is defined by a set of architectural constraints. An API that follows them gets scalability, evolvability, and cacheability almost for free. You do not need every constraint perfectly, but knowing them tells you which corners you are cutting.
The six constraints
Section titled “The six constraints”flowchart TD REST --> CS[Client–Server] REST --> ST[Stateless] REST --> CA[Cacheable] REST --> UI[Uniform Interface] REST --> LS[Layered System] REST --> COD[Code on Demand optional]
- Client–Server — separate the UI/consumer from data storage; they evolve independently.
- Stateless — each request carries everything the server needs; no per-client session is stored between calls. This is what lets you add servers behind a load balancer freely.
- Cacheable — responses must say whether they can be cached (and for how long), so clients and intermediaries can reuse them.
- Uniform Interface — resources are identified by URIs and manipulated through a standard set of methods and representations. This is the constraint that makes an API feel “RESTful”.
- Layered System — a client cannot tell whether it talks to the origin server or an intermediary (proxy, gateway, cache).
- Code on Demand (optional) — servers may send executable code to extend the client; rarely used for APIs.
Why statelessness pays off
Section titled “Why statelessness pays off”Because the server keeps no session, any server can handle any request. That makes horizontal scaling and retries simple — but it means the client must send its identity (a token) and any needed context on every request.
Common mistakes
Section titled “Common mistakes”Server-side session state Symptom:
- The server keeps a shopping cart in in-memory session state
- Scale to two servers and the cart disappears when a request lands on the other one
- Keep state on the client or in a database, not in server memory
Breaking uniform interface with a special-purpose endpoint Symptom:
POST /users/searchinstead ofGET /users?q=john- A POST with unclear side effects — can’t be cached, isn’t idempotent
- Use
GETplus query parameters for search/filtering
💡 Real-world examples
AWS API:
- Stateless authentication — every request carries its own signature (SigV4)
- No session — every request authenticates independently
Stripe API:
- A textbook uniform interface — resource-based URIs, methods that express intent
- Works behind CDNs and reverse proxies without any client changes
Sources: AWS Signature Version 4, Stripe API reference