Loading learning content...
Every time you use a mobile app to check the weather, browse products on an e-commerce site, or interact with a social media platform, you're likely communicating with a REST API. REST—Representational State Transfer—has become the de facto standard for designing web APIs, powering everything from small startups to the largest distributed systems on the planet.
But REST is frequently misunderstood. Many developers equate REST with "using HTTP," assume it simply means "returning JSON," or believe that any URL-based API is automatically RESTful. These misconceptions lead to APIs that are inconsistent, difficult to evolve, and frustrating for consumers.
In this page, we'll go back to first principles. We'll explore what REST actually is, where it came from, and why its architectural constraints enable scalable, evolvable, and maintainable APIs. By understanding REST deeply, you'll be equipped to design APIs that stand the test of time.
By the end of this page, you will understand REST as an architectural style rather than a technology. You'll know the six constraints that define REST, understand why each constraint matters, and be able to evaluate whether an API truly follows REST principles. This foundation prepares you for designing resources, methods, and responses in subsequent pages.
REST was introduced in 2000 by Roy Fielding in his doctoral dissertation at the University of California, Irvine. Fielding wasn't inventing something new from scratch—he was analyzing and formalizing the architectural principles that made the World Wide Web successful.
As one of the principal authors of the HTTP/1.1 specification and a co-founder of the Apache HTTP Server project, Fielding had unique insight into what made the web work at scale. His dissertation, titled "Architectural Styles and the Design of Network-based Software Architectures," abstracted these principles into a set of architectural constraints that any distributed system could adopt.
Key insight: REST is not a protocol, not a standard, and not a technology. It is an architectural style—a coordinated set of constraints that, when applied together, produce certain desirable properties in a distributed system.
The World Wide Web itself is the largest and most successful REST application ever built. When you browse the web—clicking links, submitting forms, navigating between pages—you're participating in a RESTful interaction. Browsers cache resources, follow hyperlinks, and process hypermedia (HTML), all without any prior knowledge of specific websites.
Why did REST emerge?
Before REST became dominant, enterprise systems commonly used approaches like:
These approaches often created tightly coupled systems that were difficult to scale and evolve. REST offered an alternative: an architecture based on the same principles that allowed the web to scale from a few academic servers to billions of users.
| Era | Approach | Characteristics | Limitations |
|---|---|---|---|
| 1980s-1990s | RPC/CORBA | Remote procedure calls, language-specific bindings, binary protocols | Tight coupling, firewall unfriendly, complex versioning |
| Late 1990s | SOAP/WS-* | XML-based messaging, extensive specifications, enterprise focus | Verbose, complex tooling required, hard to debug |
| 2000s-Present | REST | Resource-oriented, HTTP-based, stateless, hypermedia-driven | Requires discipline to implement correctly, not ideal for all use cases |
| 2010s-Present | GraphQL/gRPC | Query-based (GraphQL) or efficient binary (gRPC) | Different tradeoffs; often used alongside REST |
REST is defined by a set of architectural constraints. When a system satisfies all these constraints, it gains specific architectural properties that make it suitable for large-scale, evolvable distributed systems.
This is a fundamental point that many developers miss: REST is not defined by specific technologies like HTTP or JSON. You could theoretically build a RESTful system over other protocols (though HTTP's design makes it a natural fit). What makes a system RESTful is adherence to the constraints, not the underlying technology.
Let's examine each constraint in detail:
The first constraint separates user interface concerns from data storage concerns. This separation of concerns allows each to evolve independently.
What this means in practice:
Benefits:
Each request from client to server must contain all information necessary for the server to understand and process the request. The server cannot rely on any stored context from previous requests—there is no session state on the server between requests.
What this means in practice:
Benefits:
Statelessness doesn't mean the server can't store data—of course it can! It means the server doesn't store per-client session state. The client's state is managed by the client. Resources on the server (like user profiles, orders, products) absolutely persist; what doesn't persist is conversational context about what the client 'just did.'
Responses must explicitly or implicitly label themselves as cacheable or non-cacheable. When a response is cacheable, clients (and intermediaries) can reuse that response for equivalent requests.
What this means in practice:
Cache-Control, ETag, and Last-Modified control cachingBenefits:
The uniform interface is the central distinguishing feature of REST. It requires that the interface between clients and servers be standardized and consistent, enabling independent evolution.
The uniform interface is further characterized by four sub-constraints:
Identification of resources: Resources are identified by URIs. Each resource has a unique identifier.
Manipulation of resources through representations: When a client holds a representation of a resource (e.g., JSON), that representation contains enough information for the client to modify or delete the resource.
Self-descriptive messages: Each message contains enough information to describe how to process it (e.g., content type headers tell the client how to parse the response).
Hypermedia as the Engine of Application State (HATEOAS): Clients discover available actions through hyperlinks provided in responses, rather than through out-of-band documentation.
Benefits:
HATEOAS is perhaps the most powerful—and most frequently ignored—REST constraint. Most APIs called 'RESTful' today don't implement HATEOAS. Instead, clients hardcode URL patterns from documentation. While pragmatic, this creates coupling that true REST architecture avoids. We'll explore HATEOAS tradeoffs more deeply later.
The architecture can be composed of hierarchical layers, where each layer cannot see beyond the next layer it interacts with. A client cannot tell whether it's connected directly to the origin server or to an intermediary.
What this means in practice:
Benefits:
This is the only optional constraint. REST allows servers to extend client functionality by transferring executable code (like JavaScript).
What this means in practice:
Benefits:
Tradeoffs:
This constraint is used extensively in the web (think of any website with JavaScript), but is rarely explicitly discussed in API design contexts.
Understanding how the REST constraints work together is easier with a visual representation. The diagram below shows how a typical RESTful interaction flows through the constrained architecture:
Key observations from this architecture:
When you apply REST constraints together, you gain specific architectural properties. This is the payoff for following the constraints—these properties are why REST works well for web-scale systems:
| Property | Enabled By | Description |
|---|---|---|
| Performance | Cacheability, Statelessness | Caching reduces latency; statelessness enables efficient load distribution |
| Scalability | Statelessness, Layered System, Client-Server | No server-side session state means horizontal scaling is straightforward |
| Simplicity | Uniform Interface | One consistent interface style reduces complexity for both implementers and consumers |
| Modifiability | Client-Server, Layered System | Components can be modified independently without system-wide impact |
| Visibility | Statelessness, Self-descriptive Messages | Individual requests can be monitored, logged, and debugged in isolation |
| Portability | Client-Server, Uniform Interface | Client implementations can work across different servers following the same interface |
| Reliability | Statelessness | Server failures don't lose client state; any server can continue processing |
Following REST constraints makes these properties achievable, not automatic. You can absolutely build an unscalable REST API with poor resource modeling or blocking operations. REST provides the architectural foundation; engineering excellence builds upon it.
At the core of REST is the concept of resources. A resource is any concept that can be the target of a reference—anything important enough to be identified and linked to.
Key principles about resources:
Resources are nouns, not verbs: A resource represents a thing, not an action. You have an /orders resource, not a /createOrder endpoint.
Resources have identity: Each resource has a unique identifier (URI) that distinguishes it from all other resources.
Resources have representations: When you request a resource, you receive a representation of its state (e.g., a JSON document). The representation is not the resource itself—it's a snapshot of the resource's state.
Resources may have multiple representations: The same resource might be available as JSON, XML, HTML, or other formats, selected through content negotiation.
/users — collection of users/users/123 — specific user/users/123/orders — user's orders/products — collection of products/orders/456/items — items in an order/search?q=laptop — search results resource/getUser?id=123 — action in URL/createOrder — verb-based endpoint/deleteProduct/456 — action as path/api/processPayment — RPC-style/updateUserProfile — action in URL/doSearch — verb instead of nounThis distinction is subtle but important. Consider the resource /users/123:
{"id": 123, "name": "Alice", "email": "alice@example.com"}The resource remains constant (user 123 exists), but its representations can vary:
This separation allows for flexibility in how resources are served without changing the fundamental resource identity.
1234567891011121314
// GET /users/123// Accept: application/json { "id": 123, "name": "Alice Thompson", "email": "alice@example.com", "createdAt": "2024-01-15T10:30:00Z", "links": { "self": "/users/123", "orders": "/users/123/orders", "profile": "/users/123/profile" }}One of the most common mistakes in API design is building an RPC-style API while calling it REST. Understanding this distinction is crucial for effective API design.
RPC (Remote Procedure Call) treats network communication like function calls:
REST treats network communication as resource manipulation:
| Scenario | RPC-Style (Anti-pattern) | REST-Style (Recommended) |
|---|---|---|
| Create a user | POST /createUser | POST /users |
| Get a user | GET /getUser?id=123 | GET /users/123 |
| Update a user | POST /updateUser | PUT /users/123 or PATCH /users/123 |
| Delete a user | POST /deleteUser?id=123 | DELETE /users/123 |
| Search users | GET /searchUsers?q=alice | GET /users?q=alice |
| Place an order | POST /placeOrder | POST /orders |
| Cancel an order | POST /cancelOrder?id=456 | DELETE /orders/456 or PATCH /orders/456 with status |
| Get order items | GET /getOrderItems?orderId=456 | GET /orders/456/items |
Many APIs fall into a middle ground—using HTTP and JSON but with RPC-style semantics. These 'REST-ish' APIs miss the benefits of true REST architecture. They have the appearance of REST without the architectural properties. Recognizing this pattern is the first step toward building better APIs.
Why does this distinction matter?
Cacheability: REST's uniform interface makes GET requests naturally cacheable. RPC-style APIs often use POST for everything, preventing caching.
Predictability: With REST, if you know the resource model, you can predict the URLs and methods. RPC requires documentation for every operation.
Evolvability: REST resources can evolve (add fields, add sub-resources) without breaking clients that follow hypermedia. RPC operations often require explicit versioning.
Tooling: REST's uniform interface enables generic tooling (API gateways, caching proxies, monitoring) that understands the semantics of operations.
Leonard Richardson proposed a model for classifying APIs by how closely they adhere to REST principles. This Richardson Maturity Model provides a useful framework for evaluating and improving API designs:
POST /api with body {"action": "getUser", "userId": 123}POST /users for create, POST /users/123 for update, POST /users/123/delete for deleteGET /users/123, PUT /users/123, DELETE /users/123{"links": {"edit": "/users/123/edit", "orders": "/users/123/orders"}}While Level 3 (full HATEOAS) is theoretically ideal, Level 2 is where most successful APIs operate. The complexity of implementing and consuming hypermedia-driven APIs often outweighs the benefits for many use cases. The key is understanding the tradeoffs and making deliberate choices.
We've covered substantial ground in establishing the foundations of REST. Let's consolidate the key takeaways:
What's next:
Now that we understand REST's foundational principles, we'll apply them to practical API design. The next page explores Resource Naming—how to design clear, consistent, and intuitive URIs that properly model your domain as resources.
You now understand REST as an architectural style defined by constraints that produce desirable properties for distributed systems. This conceptual foundation enables you to evaluate APIs critically and design APIs that truly follow REST principles, not just the superficial appearance of REST.