REST APIs have become ubiquitous in modern web development, powering the majority of web services we interact with daily. Despite their popularity, many developers only have a superficial understanding of what makes an API RESTful. By diving deep into the 6 key characteristics that define REST APIs, you‘ll gain the foundational knowledge to design better APIs and use them more effectively in your web projects.
A Brief History of REST
The term REST, which stands for Representational State Transfer, was coined by computer scientist Dr. Roy Fielding in his influential 2000 doctoral dissertation. Fielding had been one of the principal authors of the HTTP specification and he used REST to describe the architectural principles behind the design of the modern web.
Since then, RESTful APIs have become the dominant approach for building web services. Almost every major web company provides a public REST API and countless more use them internally. Understanding REST has become an essential skill for web developers.
While you could dig through Dr. Fielding‘s 180-page dissertation to learn about REST, in this article we‘ll break down the core concepts in a more approachable way. We‘ll examine each of the 6 key characteristics of REST APIs, explaining what they mean, why they‘re important, and how you can apply them in practice.
By the end, you‘ll have a solid grasp of REST fundamentals that will make you a better API designer and consumer. Let‘s get started!
1. Client-Server Architecture
The first characteristic of REST APIs is that they follow a client-server architecture. But what does that mean exactly?
In a client-server model, the client and the server are separate entities that communicate over a network. The client is responsible for the user interface and user interactions, while the server handles data storage and business logic.
This separation of concerns offers several benefits:
- It allows the client and server to evolve independently, as long as the interface between them remains the same. Client code can be changed without impacting the server, and vice versa.
- It improves portability, since the same server can support multiple client types (web, mobile, desktop, etc.).
- It enables better scalability, since clients and servers can be scaled independently based on load.
In the context of web APIs, the client is typically a web browser or mobile app, while the server is the remote web server exposing the API. By strictly adhering to a client-server architecture, REST APIs can provide a clean, flexible interface between these two components.
2. Stateless
The next key characteristic of REST is statelessness. A stateless protocol is one in which the server does not keep any data related to the client session on the server side.
In practice, this means each request from the client to the server must contain all the information necessary for the server to understand and process that request. The server cannot rely on any context stored from previous requests.
The primary benefit of stateless design is improved scalability. When a server doesn‘t have to maintain session state, it frees up resources and allows any server in a cluster to handle any request from any client. With no session data to track, spinning up additional servers to handle increased load becomes much easier.
The tradeoff is that requests may be larger in size, since authentication tokens and other metadata must be included in every request, rather than stored on the server. However, this can be mitigated through techniques like token compression and caching.
To be considered RESTful, an API must not rely on implicit server-side context. All session state should be kept on the client and passed to the server when needed. While it takes some additional work, the scalability benefits make statelessness a key feature of REST APIs.
3. Cacheable
Caching is a critical aspect of optimizing web performance, and REST APIs embrace it as a first-class characteristic.
In a REST API, server responses should explicitly label themselves as cacheable or non-cacheable. If a response is cacheable, the client can reuse that response data for later equivalent requests, rather than sending a new request to the server.
Even a short cache duration, on the order of seconds, can drastically reduce the number of requests a busy API server needs to handle. At large scale, effective caching can be the difference between a high-performance API and one that crumbles under load.
Of course, caching introduces some complexity in terms of cache validation and invalidation. Clients need a way to know when their cached data is stale and should be refreshed from the server. Common strategies include using ETags, expiration times, and cache-control headers.
When used properly, caching is a powerful tool for reducing server load, minimizing network traffic, and speeding up client apps. REST APIs that make full use of caching can provide a better experience for both API providers and consumers.
4. Layered System
REST APIs should be designed as a layered system, meaning the API is composed of multiple layers, each with a specific responsibility. A key principle is that each layer should only interact with the layer directly below it.
For example, a typical web API might include the following layers:
- The client layer (web browser or mobile app)
- An API gateway layer for request routing and authentication
- The actual application layer that implements the API business logic
- A persistence layer for interacting with databases or other storage services
The main benefit of a layered architecture is encapsulation. Each layer can be developed, deployed, and scaled independently. Changes in one layer don‘t impact the others, as long as the interfaces between them remain consistent.
This modularity makes it easier to evolve the system over time. For example, you could switch out your database layer from a relational database to a NoSQL store without needing to change your API contract. Or you could add a caching layer to improve performance without modifying the core application code.
A layered design also enables load balancing and improved security, since requests can be routed through dedicated layers for those purposes. The API consumer only interacts with the outermost layer, and is unaware of (and unaffected by) the inner layers and their implementation details.
Adhering to a layered system architecture helps make a REST API more maintainable, scalable, and flexible over the long term. It adds some upfront complexity, but pays dividends as the API grows and evolves.
5. Code on Demand (Optional)
Of the 6 REST characteristics, Code on Demand is the only one that is considered optional. It‘s also the least commonly used in practice, for reasons we‘ll discuss.
With Code on Demand, a REST API can return executable code from the server in response to a client request. The client can then download and execute this code to extend its functionality as needed.
In theory, Code on Demand offers some interesting capabilities. An API could provide client-specific logic, or enable dynamic plugin architectures. The server could update client behavior without requiring a new client release.
However, Code on Demand has some significant drawbacks that have limited its adoption:
- Security risks: Executing remotely downloaded code on a client device opens up major security vulnerabilities if not implemented very carefully.
- Compatibility issues: Clients must support the language and runtime of the downloaded code snippets.
- Increased complexity: Dynamically downloading and executing code adds significant complexity compared to traditional static client codebases.
Due to these concerns, Code on Demand is rarely seen in modern REST APIs. Instead, most API providers rely on traditional means of extending and updating client functionality, such as releasing new client library versions or providing configurable endpoints.
While Code on Demand is an interesting capability in theory, its practical drawbacks make it more trouble than it‘s worth for most REST APIs. Feel free to experiment with it, but know that it‘s entirely optional for an API to be considered RESTful.
6. Uniform Interface
The final and most important characteristic of REST APIs is the uniform interface. This means that all API requests for the same resource should look the same, no matter where the request comes from. The REST API should provide a consistent, standardized way of accessing and manipulating resources.
Fielding‘s dissertation describes four key aspects of a uniform interface:
- Resource identification in requests: Each resource must be uniquely identifiable via a URI.
- Resource manipulation through representations: When a client has a representation of a resource, it should have enough information to be able to modify or delete that resource.
- Self-descriptive messages: Each request and response should include enough metadata to describe how it should be processed, such as media type and cacheability.
- Hypermedia as the engine of application state (HATEOAS): Clients should only interact with resources and other application states through the hyperlinks and representations provided dynamically by the server.
The big benefit of a uniform interface is that it completely decouples clients from servers. The client doesn‘t need to know anything about the server implementation in order to interact with it. All it needs is the API contract, which should remain consistent even as the server implementation changes over time.
This decoupling enables APIs and clients to evolve independently, as long as the uniform interface contract is maintained. It also makes it easier to understand and interact with an unfamiliar API, since all resources are accessed and manipulated in a consistent way.
There are some design best practices to follow to provide a truly uniform interface:
- Use nouns instead of verbs in endpoint paths.
- Provide filtering, sorting, and pagination options as query parameters.
- Use HTTP status codes to indicate the result of operations.
- Support common media types like JSON and XML.
- Use semantic versioning to handle changes to the API contract over time.
Anti-patterns to avoid include using inconsistent endpoint naming schemes, using GET requests to modify data, omitting important metadata from requests and responses, and requiring clients to construct their own URLs.
A well-designed, uniform API interface is arguably the most important aspect of a REST API. It takes some discipline to get right, but the long-term benefits of maintainability, discoverability, and consistency are well worth the effort.
Conclusion
We‘ve covered a lot of ground in this deep dive into the key characteristics of REST APIs. Understanding and applying these principles is essential for designing and using web APIs that are scalable, maintainable, and performant.
To recap, the 6 key characteristics of REST APIs are:
- Client-Server Architecture
- Stateless
- Cacheable
- Layered System
- Code on Demand (Optional)
- Uniform Interface
While it takes some effort to fully adhere to these REST principles, doing so will result in higher-quality, more scalable APIs. I encourage you to dig even deeper into these concepts, as well as explore other API architectural styles like GraphQL, gRPC, and event-driven architectures.
And if you‘re looking to put these concepts into practice, check out ScrapingBee‘s RESTful API for all your web scraping needs. With a simple, uniform interface and a generous free tier, it‘s a great example of REST best practices in action.
Now go forth and build amazing APIs! ✨