REST vs SOAP. REST vs GraphQL. JSON vs XML. There are many dichotomies in the world of API design. It seems for each architectural choice there exists an opposite solution purpose-built for a specific application. We can see this in issues like statelessness and statefulness, as well as functional choices such as SOAP and REST.
Today, we’re going to look at one such dichotomy: REST and Streaming APIs. These two options are fundamentally different in a variety of ways, not the least of which is their essential relationship between the client and the server. For this reason, the architectures bear comparison, and the solutions present in each field bear some further discussion.
Keep in mind that much of this piece will be using generalities and there are bound to be edge cases. Consider this a general overview of the standard use cases behind REST and Streaming APIs, as well as the standard architectures, approaches, and natures one would expect from each.
Comparing REST and Streaming APIs
Despite the number of proponents of so-called “REST-like” solutions, REST is actually well-defined in constraints – its creator, Roy Fielding, has laid out several key constraints that make up a REST API.
First, a REST API functions in a client-server architecture. By design, RESTful APIs separate the concerns held by the client and by the server, allowing for each to evolve independently of one another. This also means that the typical flow of information in such a relationship is fundamentally a request/response paradigm – a client requests something, and the server responds with the requested information.
Secondly, and principal to the name itself (REST is short for Representational State Transfer), RESTful APIs are stateless. The API itself holds no client context on the server beyond that relevant to the immediate request and the information needed to authenticate the client. While it is technically true that this state can be stored elsewhere, like in a database, and thus would not “technically” be stored in the API itself, that’s not really “state” as much as it is “stored context”.
Speaking of stored context, REST APIs are cacheable. They can store data that has been previously requested, and then serve that data upon demand. In theory, they should also be able to extend their capabilities temporarily through the use of executable extensions – this is completely optional, however.
Finally, REST APIs should be somewhat obfuscated to the end user, with a layered API system of intermediaries and primary servers being able to carry out instruction without exposing their position in the hierarchy to the end user. This is largely a requirement to provide for scalability and load balancing, although there are additional benefits to this approach – namely, increases in security by reducing the visibility of attack vectors, the ability to distribute and share cached information over differently geolocated caches, and redundancy in server function to ensure optimum uptime.
- Justification: REST is by its very design stateless, highly scalable, and flexible in output. It is designed around the request-response model. For this reason, REST is most useful in environments where the client might request a wide range of calls, where the server can respond with varied and different data, and where the hypermedia being supported requires flexible, scalable, and changeable architectures.
- Examples: Some good REST examples include api.video (providing RESTful video delivery) and the Skyscanner Travel APIs (providing tools to compare flight, car, and hotel prices).
Streaming APIs are almost an exact opposite of the REST ethos. In its most basic state, Streaming APIs invert the conversational nature of REST, where a request is made and a response is given, and instead has the server send information to a client when an update is ready. While the client can, in theory, request an update, the streaming server should preempt this with updates as ready.
This is a total inversion of the REST paradigm – whereas REST APIs are stateless, Streaming APIs are by their very nature stateful. Without storing state in some form, the Streaming API cannot properly contextualize the data relationship with the requesting client. In other words, clients typically open persistent connections with the streaming server in question. While this connection certainly has a limited lifespan, it is during this connection that the pushed content is delivered.
If REST APIs are a conversation, Streaming APIs are more akin to watching a movie in a movie theater – if REST is two people talking, a Streaming API is a person buying a movie ticket, sitting in a theater, and passively receiving the film.
One major difference that should be mentioned is that Streaming APIs have a lot less flexibility in content type versus REST. Because REST is a request/response model, the initial request holds all of the information required to carry out that request. Thus, when a request is made, in some applications (such as GraphQL), the format or content type can be stated as an expected supported variable.
Streaming APIs, on the other hand, typically have a strictly limited response format. Though you can sometimes request a different type, you’re stating this up front, not as part of your request – and often, this isn’t even supported at all. In other words, you get what the server provides.
- Justification: Streaming APIs support an opposite use case from REST. They are best used when a client is requesting unique, known, formatted data from a server or service. Data is less requested and processed for a response than it is requested from already generated data, and as such, streaming is more appropriate in such a use case where the interaction is less conversational and is more informational in nature.
- Examples: Some examples of Streaming APIs include the Twitter API (PowerTrack, Volume, and Replay providing real-time data, Tweet metadata for ingesting, and generalized data) and the real-time Salesforce API (allowing for PushTopic and Data Capture event triggers).
REST Supporting Architecture
REST is fundamentally a request/response type relationship between client and server. Something is requested, something is done, and then something is sent in return. This exchange is a conversation – for this reason, REST architecture is usually designed around the idea of providing highly modular micro-solutions for given use cases.
The underpinning architecture behind the entirety of REST is the modular web server. This may take the form a physical servers or virtual servers, but ultimately, the idea of nodes that can quickly spin up or spin down is very core to the RESTful microservice-heavy landscape that dominates most of the enterprise REST landscape.
These servers also have a very specific requirement – they must be able to support both the bandwidth of requests and the resultant bandwidth of custom output required. Even with lightweight solutions, this is still a fundamental requirement of the REST server node – it must be able to converse.
It should be noted that much of REST is based around standard HTTP transport and verbiage. For that reason, a lot of RESTful interaction is going to be at least supported by, if not principally guided using, HTTP status and error codes. While this is not unique to REST, many architectural choices have been made to support the use of these codes and to have them trigger certain actions within RESTful implementations.
Streaming Supporting Architecture
Streaming APIs are an inversion of the RESTful approach, and for this reason, much of the underlying architecture diverges from what is required with REST. REST requires high-bandwidth request and response-oriented servers – streaming APIs, on the other hand, utilize event brokers to manage this interaction.
In a streaming scenario, it’s not a conversation, and thus, the hardware doesn’t really need to support that. What the software needs to support is a simple method of storing the status of an open connection or a long-term requester, and then send the same information globally to each group of users.
This is very different from REST, and as such, much of the basic conceptual approach to architecture changes in its root purpose. Scalability is now less a concern of supporting higher request volume and instead is principally around supporting larger amounts of compute to updated clients and open connects.
Streaming still operates over the same HTTP methods as REST, but because of its event-driven interactions, the relationship shifts power from the requesting client to the providing server. As such, the “client-centric” worldview of verbiage and request strategy should be reversed, instead of turning “what can I request from the server” to “how is the endpoint on the server useful to me”.
In short, REST and Streaming APIs have very different stacks, and for good reason – they support fundamentally different workflows for different use cases. This means the architecture is different and largely speaking, built for different purposes. Understanding these differences can help identify specific value behind each implementation, as well as the underlying core functions that make these approaches possible.
What are your thoughts on streaming and RESTful APIs? Can RESTful APIs function in the streaming space? Let us know in the comments below!