Communication Protocol
Request/Response API
1. Representational State Transfer (REST): making data available as resources
Pros
Decoupled client and server
Decoupling the client and the server as much as possible, REST allows for a better abstraction than RPC. A system with abstraction levels is able to encapsulate its details to better identify and sustain its properties. This makes a REST API flexible enough to evolve over time while remaining a stable system.
Cache-friendly
Reusing a lot of HTTP tools, REST is the only style that allows caching data on the HTTP level. In contrast, caching implementation on any other API will require configuring an additional cache module.
Multiple formats support
The ability to support multiple formats for storing and exchanging data is one of the reasons REST is currently a prevailing choice for building public APIs.
Cons
No single REST structure
There’s no exact right way to build a REST API. How to model resources and which resources to model will depend on each scenario. This makes REST simple in theory, but difficult in practice.
Big payloads
REST returns a lot of rich metadata so that the client can understand everything necessary about the state of the application just from its responses.
And this chattiness is no big deal for a big network pipe with lots of bandwidth capacity. But that’s not always the case.
This was the key driving factor for Facebook coming up with the description of GraphQL style in 2012.
Common Mistake
The main benefit of using GraphQL is the ability to send a query that specifies only the information you need and receiving exactly that.
However, you can achieve this same effect using REST, by passing the name of the fields you want to use in the URL, then implementing the parsing and returning logic yourself:
GET /books/1492030716?fields=title,pageCount
If you want to use a query language in REST APIs, a solution like OData is a great alternative. OData, short for Open Data Protocol, was originally developed by Microsoft in 2007.
OData is an open protocol that enables you to create and consume queryable and interoperable RESTful APIs in a simple, standard way.
OData gives you a rich set of querying capabilities and is quickly gaining ground for its open source approach and exceptional scalability.
Use Case
Management APIs
APIs focused on managing objects in a system and intended for many consumers are the most common API type. REST helps such APIs to have strong discoverability, good documentation, and it fits this object model well.
Simple resource-driven apps
REST is a valuable approach for connecting resource-driven apps that don’t need flexibility in queries.
2. Remote Procedure Call (RPC): invoking a function on another system
Pros
Straightforward and simple interaction
RPC uses GET to fetch information and POST for everything else. The mechanics of the interaction between a server and a client come down to calling an endpoint and getting a response.
Easy-to-add functions
If we get a new requirement for our API, we can easily add another endpoint executing this requirement:
- Write a new function and throw it behind an endpoint and
- now a client can hit this endpoint and get the info meeting the set requirement.
High performance
Lightweight payloads go easy on the network providing high performance, which is important for shared servers and for parallel computations executing on networks of workstations.
RPC is able to optimize the network layer and make it very efficient with sending tons of messages per day between different services.
Cons
Tight coupling to the underlying system
An API’s abstraction level contributes to its reusability. The tighter it is to the underlying system, the less reusable it will be for other systems.
RPC’s tight coupling to the underlying system doesn’t allow for an abstraction layer between the functions in the system and the external API.
This raises security issues as it’s quite easy to leak implementation details about the underlying system into the API.
An RPC’s tight coupling makes scalability requirements and loosely coupled teams hard to achieve.
So, the client either worries about any possible side effects of calling a particular endpoint or tries figuring out what endpoint to call because it doesn’t understand how the server is naming its functions.
Low discoverability
In RPC there’s no way to introspect the API or send a request and start understanding what function to call based on its requests.
Function explosion
It’s so easy to create new functions. So, instead of editing the existing ones, we create new ones ending up with a huge list of overlapping functions that are hard to understand.
Use Case
Command API
An RPC is the proper choice for sending commands to a remote system. For instance, a Slack API is very command-focused: Join a channel, leave a channel, send a message. So, the designers of the Slack API modeled it in an RPC-like style making it small, tight, and easy to use.
Customer-specific APIs for internal microservices
Having direct integration between a single provider and consumer, we don’t want to spend a lot of time transmitting a lot of metadata over the wire, like a REST API does.
With high message rate and message performance, gRPC and Twirp are strong cases for microservices.
Using HTTP 2 under the hood, gRPC is able to optimize the network layer and make it very efficient with sending tons of messages per day between different services.
However, if you’re not aiming at high network performance, but rather at a stable API contact between teams publishing highly distinctive microservices, REST will ensure that.
3. GraphQL
Pros
Typed schema
GraphQL publishes in advance what it can do, which improves its discoverability. By pointing a client at the GraphQL API, we can find out what queries are available.
Fits graph-like data very well
Data that goes far into linked relations but not good for flat data.
No versioning
The best practice with versioning is not to version the API at all.
While REST offers multiple API versions, GraphQL uses a single, evolving version that gives continuous access to new features and contributes to cleaner, more maintainable server code.
Flexible permissions
GraphQL allows for selectively exposing certain functions while preserving private information. Meanwhile, REST architecture doesn’t reveal data in portions. It’s either all or nothing.
Cons
Performance issues
GraphQL trades off complexity for its power. Having too many nested fields in one request can lead to system overload.
For complex queries, a REST API might be easier to design because you can establish multiple endpoints for specific needs, and you can fine-tune specific queries to retrieve the data in an efficient way.
This might be a bit controversial because multiple network calls can still take a lot of time. But, if you’re not careful, a few big queries can bring your server down dramatically. In that sense, GraphQL’s greatest strength can also be its greatest weakness.
In a GraphQL API, tools like Dataloader allow you to batch and cache database calls. But, in some cases, even this isn’t enough, and the only solution is to block queries by calculating a maximum execution cost or query depth. Any of these solutions will depend on the library you’re using.
Caching complexity
As GraphQL isn’t reusing HTTP caching semantics, it requires a custom caching effort.
Use Case
Data fetching control
GraphQL was designed to allow the client to ask for only the data it needs. While the server might be able to deliver more data to the client for a single request, it would only send the data requested by the client.
If you want the client to control the type and amount of data it needs, GraphQL would be ideal for your project.
Complex systems and microservices
GraphQL is able to hide the complexity of multiple systems integration behind its API. Aggregating data from multiple places, it merges them into one global schema.
This is particularly relevant for legacy infrastructures or third-party APIs that have expanded over time.