The Six REST Constraints
REST is defined by six architectural constraints. An API is truly "RESTful" only when it follows all of these constraints.
1. Client-Server Architecture
The client and server are separate and can evolve independently. The client doesn't need to know how data is stored, and the server doesn't need to know how data is displayed.
Benefits:
- Teams can work independently on client and server
- Either side can be replaced without affecting the other
- Multiple clients (web, mobile, CLI) can use the same API
┌─────────────┐ ┌─────────────┐
│ Client │ ──────► │ Server │
│ (React) │ ◄────── │ (Node.js) │
└─────────────┘ └─────────────┘
2. Statelessness
Each request must contain all information needed to process it. The server doesn't store session state between requests.
Bad (Stateful):
POST /login
{ "username": "john", "password": "secret" }
GET /my-profile ← Server remembers who you are
Good (Stateless):
GET /users/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs... ← Token contains identity
Benefits:
- Easy to scale horizontally (any server can handle any request)
- Simpler server implementation
- Better reliability (server restart doesn't lose state)
3. Cacheability
Responses must define themselves as cacheable or non-cacheable. This prevents clients from reusing stale data and enables efficient caching.
HTTP/1.1 200 OK
Cache-Control: max-age=3600
ETag: "abc123"
{
"id": 1,
"title": "Cached Product"
}
Benefits:
- Reduced server load
- Faster response times
- Lower bandwidth usage
4. Uniform Interface
This is the most fundamental REST constraint. It simplifies architecture by having a consistent way to interact with resources.
The uniform interface has four sub-constraints:
a) Resource Identification
Resources are identified by URIs:
/users/123
/products/abc
b) Resource Manipulation Through Representations
When you want to modify a resource, you send a representation:
PUT /users/123
Content-Type: application/json
{ "name": "New Name" }
c) Self-Descriptive Messages
Each message contains enough information to process it:
GET /users HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer token123
d) Hypermedia as the Engine of Application State (HATEOAS)
Responses include links to related resources:
{
"id": 123,
"name": "John",
"links": {
"self": "/users/123",
"orders": "/users/123/orders",
"profile": "/users/123/profile"
}
}
5. Layered System
The architecture can be composed of hierarchical layers. A client can't tell if it's connected directly to the end server or an intermediary.
┌────────┐ ┌───────────┐ ┌──────────┐ ┌────────┐
│ Client │ ─► │ CDN/Cache │ ─► │ Load │ ─► │ Server │
└────────┘ └───────────┘ │ Balancer │ └────────┘
└──────────┘
Benefits:
- Add caching, load balancing, or security layers transparently
- Improved scalability
- Separation of concerns
6. Code on Demand (Optional)
Servers can extend client functionality by sending executable code (like JavaScript). This is the only optional constraint.
<script src="https://api.example.com/widgets/chart.js"></script>
Exercise: Identify Constraint Violations
Summary
| Constraint | Key Point |
|---|---|
| Client-Server | Separation of concerns |
| Stateless | No server-side session |
| Cacheable | Responses must be cacheable |
| Uniform Interface | Consistent resource interaction |
| Layered System | Transparent intermediaries |
| Code on Demand | Optional executable code |
Understanding these constraints helps you design APIs that are truly RESTful and gain all the benefits of the REST architecture.

