REST is not a protocol, and it’s not a piece of software I can install. It is an architectural style — a set of design constraints that, when followed together, produce systems with certain useful properties: scalability, simplicity, and reliability.
Roy Fielding defined six guiding constraints for REST in his year 2000 doctoral dissertation. In this article, I want to go through each one properly, because most explanations rush past them, and understanding these constraints is really what separates a “REST API” from just “an API that returns JSON.”
1. Client-Server Architecture
The client (which asks for things) and the server (which stores and manages data) are separated. This separation means the client and server can evolve independently — I can redesign a mobile app’s interface without touching the backend, and I can upgrade backend infrastructure without breaking the app.
This separation is one of the most practical benefits of REST in real teams: frontend developers and backend developers can work almost completely independently, as long as they agree on the API contract between them.
2. Statelessness
Each request from a client to a server must contain everything the server needs to understand and process it. The server does not store any session information about the client between requests. If authentication is needed, the client must send proof of identity (like a token) with every single request, not just the first one.
This makes REST APIs easier to scale, because any server in a cluster can handle any request — there’s no need to always route a user back to the “same” server that remembers them. This is a huge deal for large systems: it means I can add or remove backend servers freely, using a load balancer to spread traffic across all of them, without worrying about which specific server “remembers” a given user.
3. Cacheability
Responses must define themselves as either cacheable or non-cacheable. If a response is cacheable, the client (or something in between, like a browser or a proxy) can reuse that response for identical future requests, which reduces load on the server and speeds things up for the user.
In practice, this is done through HTTP headers like Cache-Control and ETag. A well-designed REST API marks data that rarely changes (like a list of country codes) as cacheable for a long time, while marking frequently changing data (like a live stock price) as non-cacheable or cacheable only for a few seconds.
4. Uniform Interface
This is the heart of REST, and honestly the constraint that gives REST its name and its main value. It means that resources are identified through consistent, predictable URLs, and interactions with those resources follow standard, well-known methods (the HTTP methods).
A uniform interface makes an API predictable and easy to learn, since once I understand the pattern for one resource, I understand the pattern for all of them. The uniform interface constraint itself is usually broken down into four smaller sub-principles:
- Identification of resources — each resource (like a specific user or order) has its own unique URL.
- Manipulation of resources through representations — I interact with a representation of the resource (like a JSON object), not the actual underlying data structure on the server.
- Self-descriptive messages — each request and response contains enough information (like headers describing the content type) to be understood on its own.
- Hypermedia as the engine of application state (HATEOAS) — responses can include links to related actions or resources, letting a client discover what it can do next just by reading the response, rather than needing that knowledge hardcoded in advance. This particular sub-principle is the least commonly implemented in real-world APIs, but it’s part of Fielding’s original definition.
5. Layered System
A client doesn’t necessarily know, or need to know, whether it’s talking directly to the actual server or to an intermediary — like a load balancer, a caching layer, or a security gateway. Layers can be added or changed without disrupting the overall system, as long as each layer still speaks the same interface.
This is why I can add a CDN in front of an API, or introduce an API gateway for authentication and rate limiting, without the client application needing any changes at all — from the client’s point of view, it’s still just talking to “the API.”
6. Code on Demand (Optional)
This is the only optional constraint in REST. It allows a server to send executable code (like JavaScript) to a client, which the client can run to extend its own functionality.
This one is less commonly used in typical REST API design today, since most REST APIs just exchange data (like JSON) rather than executable code. Web browsers loading and running JavaScript from a server is actually a classic real-world example of code on demand in action, even outside the context of typical “REST API” discussions.
Why These Constraints Matter Together
No single constraint on its own makes a system “RESTful.” It’s the combination of statelessness, a uniform interface, layering, and cacheability working together that gives REST systems their key benefits: they scale well, they’re simple to reason about, and different parts of the system can evolve independently without breaking each other.
This is also exactly why two APIs can both claim to be “REST APIs” yet feel quite different to use — some teams follow all six constraints closely, while others follow just enough of them (usually client-server separation, statelessness, and a resource-based uniform interface) to be reasonably called “RESTful” in everyday conversation.
REST vs SOAP: A Quick Historical Note
Before REST became mainstream, many Web APIs used a heavier, more complex style called SOAP (Simple Object Access Protocol), which relied on strict XML messaging formats, formal contracts, and complicated tooling. REST’s constraints achieve similar goals — reliability, structure, predictability — but with far less overhead, which is a big part of why REST overtook SOAP as the default choice for most new Web APIs.
Final Thoughts
The REST architectural style is really a set of trade-offs chosen deliberately to make distributed systems simpler, more scalable, and easier to evolve over time. Once I understood the six constraints individually, I stopped thinking of REST as just “an API that uses GET and POST” and started seeing it as a genuine design philosophy with real reasoning behind every rule.
