Not All Microservices Need to Be REST — 3 Alternatives to the Classic

Not All Microservices Need to Be REST — 3 Alternatives to the Classic

REST is not the answer to every API question

Image by Manfred Antranias Zimmer from Pixabay

When talking about microservices, for a few years now that has meant HTTP REST APIs. Granted, some of them might’ve been half-done implementations that only picked some of the features from the REST standard. However, they were all aiming for a REST implementation anyway.

And while REST is definitely a good solution when it comes to designing and implementing microservices, they’re not the only solution nor the best alternative in some situations. So let’s take a quick look at three different ways of implementing microservices that don’t include the REST standard.

SOAP

While older than REST, SOAP is still a very valid alternative, so don’t discard it just because it’s old — said every Sr. citizen at one point or another.

SOAP is a communication protocol that uses XML messages to authenticate, authorize and execute remote code. It tries to provide an interface for remote method execution.

The main complaint about SOAP is the fact that because it depends on XML for its communication layer, thus it tends to be very verbose. And because of this, it’s not the most optimized way to send data across the wire.

The following is an example of a SOAP message:

https://medium.com/media/ab89d97ee7f1eb98c4504e6761fada08/href

By reading the XML you can see we’re just trying to execute a remote method called GetStockPrice and we’re giving it one parameter, StockName with the value “T”. You can see how for that, we needed almost 20 lines of code.

However, it does have some interesting benefits we tend to forget about. You see, one of the main issues with REST is that discoverability is normally ignored. REST proposes HATEOAS as a means to discover how the interface is defined. However, given all features are optional and HATEOAS is not trivial to implement developers tend to ignore it. This forces the client to know about the structure of the API, potentially coupling both client and service together. The moment the service changes, the client is directly affected.

SOAP solved this problem by forcing discoverability as part of the protocol. For every service that publishes an API there needs to be a WSDL file describing all endpoints. This is also an XML file, one that is used by the client applications to understand how the API looks (i.e what methods are being published, which attributes do they accept, and so on).

https://medium.com/media/df9b3562155657216aedebb927cd8263/href

With that file, the service is defining multiple requests and responses. It is everything any client might need to understand the published methods.

And just like with REST, given XML is a technology agnostic medium, you can use different technologies together without any problem. SOAP is currently only used on legacy systems, but it could be an interesting solution when you need auto-discoverability to be the main feature without having to implement your own solution.

GraphQL

Now, if you want to talk about new, GraphQL is the newest kid in town (I mean, it’s been out since 2015, but it’s still the hottest thing around, you know?).

While REST focuses on resources and provides a set of endpoints around them to allow for multiple operations, GraphQL focuses on the data. It is more a query language than an actual API, although it does provide all the required tools to access the queried data as well.

Don’t let the name fool you though, it’s not a graph database like Neo4J is, instead its major benefit is that it allows you to query and request the exact data you need. This can be a major benefit over REST, where you’d had to query multiple resources, get extra properties you weren’t really looking for and then mix it as part of the client logic.

Imagine having a simple API around a blog, with users, their posts and their followers. If you wanted to get the posts from one particular user, their name and the last 5 followers, you’d have to do something like this with REST:

//#1. Get user name
GET /users/<ID>
/**
{
"id": "123",
"name": "Fernando Doglio",
"birthdate": "1983-10-24",
"address": {
"city": "Madrid",
"country": "Spain"
},
"phonenumber": 998392839
}
*/
//#2. Get user's posts
GET /users/<ID>/posts
/**
[{
"id": 1,
"user_id": "123",
"title": "Post #1",
"post_date": "2021-06-28",
"body": "...."
}
...
]
*/
//#3. Get last 5 followers for user
GET /users/<ID>/followers?orderBy=follow_date&desc=1&limit=5
/**
[{
"id": 1,
"user_id": "123",
"name": "Follower 1",
"follow_date": "2020-01-02",
},
{
"id": 2,
"user_id": "123",
"name": "Follower 2",
"follow_date": "2019-12-02",
}
...
]
*/

Notice there are 3 requests, and a lot of data I never mentioned as part of the ask (for instance, the user’s address nor the posts’ body). Now, it’s your client’s responsibility to discard the information it doesn’t need and then, mix everything together into a single object (or whatever data structure it may need).

Instead, if you were to perform the same query using GraphQL, you’d only have to do one single request that looks like this:

query {
User (id: "123"){
name
posts {
title
post_date
}
followers (last: 5) {
name
}
}
}

One single POST request with that information, we get all the data we need and because of how GraphQL works, the structure of the response will mimic that of the request. So we’ll get:

{
"data": {
"User": {
"name": "Fernando Doglio",
"posts": [{
"title": "Post #1",
"post_date": "2021-06-28"
}
...
],
"followers": [
{ "name": "Follower #1" },
{ "name": "Follower #2" }
]
}
}
}

As you can see, we’ve saved a lot of time only transferring the data we actually need and the client doesn’t have to do anything else, given the response is already formatted by the server.

This is especially helpful if you’re on a restricted network and need to take into consideration the cost of transferring data through the wire, like you would on a mobile device.

Another major benefit of GraphQL over REST is that you can get real-time updates from the server on specific events. This is usually done through a WebSocket connection, but it’s something that you could only dream about with REST.

This allows the communication to start on the server-side, instead of us having to code a polling mechanism on the client to get the new data as soon as we could (which does not mean as soon as it was accessible). This polling mechanism was also very bad for network traffic, given you’d be sending multiple HTTP Requests that would not yield any results.

Overall GraphQL is a major jump forward when it comes to data-intensive APIs because it helps optimize resource utilization. However, if your API is rather simple or is not meant to serve data-heavy use cases, going with GraphQL instead of REST could be overkill. Make sure that if you force GraphQL on your clients, they’ll be able to properly benefit from most of its features.

RPC

To close the list, I wanted to cover this old but goodie technique. It’s called RPC or Remote Procedure Call and it consists of allowing client code to call a piece of server code as if it was local.

In other words, the client is abstracted from the fact that the code used is not local, how to contact it and what happens with the data between each endpoint. Instead you just perform the call like you would with a local dependency.

Unlike GraphQL which was very data-centric and REST which is very resource-centric, RCP is more about action. What do you need to do? That’s the main question you ask when you build an RPC API.

If you want to look at an example, I built an RPC library in JavaScript for another article, you can check it out here:

Writing an RPC library in Node.js

But the gist of it is that I have a public definition of my API’s methods (which is essentially a WSDL-like file) and the client application will take that definition and create a set of methods during execution time, to mimic a local behavior, although the actual logic is remote.

From the example in that article, this is what you’d see as a client of that RPC API:

https://medium.com/media/ad87f64714a39b87c48d6642241bf164/href

The example is simple, but a few things are happening:

  1. The client library is being instantiated and given a host and port values. This is where the client will download the API definition from and will use it to dynamically define the correct methods.
  2. The client will trigger a ready event once it’s finished reading the definition and adding the methods. This means it’s ready to be used.
  3. We’re now calling the new method on line 15. This method could be doing anything really, but here it’s just adding 2 numbers. The key though, is that the logic for adding those numbers isn’t on the client, but rather, on the remote server.

We’re transferring data through the wire back and forth, and thanks to the defined schema from the server, we’re able to correctly send and parse back types.

Notice how the actual transfer channel and protocol were completely hidden from the client. We could’ve been using sockets for all you care, the result would’ve been the same. And that is one of the major benefits of RPC over REST, you hide the channel because your focus is the action, that’s it.

Granted, with REST you don’t need a schema defining the API, in theory, self-discovery is an option. However, that definition is required to provide the abstracted experience I just mentioned, especially in typed languages, so consider it definitely not a waste of time or resources.

Sometimes we tend to have APIs that are very action-heavy and we try to force REST onto them, by coming up with abstract resources and assigning functions around them. Instead, consider that REST might not be the best solution for your problem, and try to use something else, like RPC which is a perfect match for such a situation.

What is your favorite REST alternative? Do you have one or are you a through and through kind of dev?

Have I left one out of the list? Leave a comment and share your thoughts on REST alternatives.

Develop & share JS components with Bit

Bit is an ultra-extensible tool that lets you create truly modular applications with independently authored, source-controlled, and maintained components.

Use it to build modular apps & design systems, author and deliver micro frontends, or simply share components between applications.

An independently source-controlled and shared “card” component (on the right, its dependency graph, auto-generated by Bit)

Bit: The platform for the modular web

Learn More


Not All Microservices Need to Be REST — 3 Alternatives to the Classic was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.

Not All Microservices Need to Be REST — 3 Alternatives to the Classic

REST is not the answer to every API question

Image by Manfred Antranias Zimmer from Pixabay

When talking about microservices, for a few years now that has meant HTTP REST APIs. Granted, some of them might’ve been half-done implementations that only picked some of the features from the REST standard. However, they were all aiming for a REST implementation anyway.

And while REST is definitely a good solution when it comes to designing and implementing microservices, they’re not the only solution nor the best alternative in some situations. So let’s take a quick look at three different ways of implementing microservices that don’t include the REST standard.

SOAP

While older than REST, SOAP is still a very valid alternative, so don’t discard it just because it’s old — said every Sr. citizen at one point or another.

SOAP is a communication protocol that uses XML messages to authenticate, authorize and execute remote code. It tries to provide an interface for remote method execution.

The main complaint about SOAP is the fact that because it depends on XML for its communication layer, thus it tends to be very verbose. And because of this, it’s not the most optimized way to send data across the wire.

The following is an example of a SOAP message:

By reading the XML you can see we’re just trying to execute a remote method called GetStockPrice and we’re giving it one parameter, StockName with the value “T”. You can see how for that, we needed almost 20 lines of code.

However, it does have some interesting benefits we tend to forget about. You see, one of the main issues with REST is that discoverability is normally ignored. REST proposes HATEOAS as a means to discover how the interface is defined. However, given all features are optional and HATEOAS is not trivial to implement developers tend to ignore it. This forces the client to know about the structure of the API, potentially coupling both client and service together. The moment the service changes, the client is directly affected.

SOAP solved this problem by forcing discoverability as part of the protocol. For every service that publishes an API there needs to be a WSDL file describing all endpoints. This is also an XML file, one that is used by the client applications to understand how the API looks (i.e what methods are being published, which attributes do they accept, and so on).

With that file, the service is defining multiple requests and responses. It is everything any client might need to understand the published methods.

And just like with REST, given XML is a technology agnostic medium, you can use different technologies together without any problem. SOAP is currently only used on legacy systems, but it could be an interesting solution when you need auto-discoverability to be the main feature without having to implement your own solution.

GraphQL

Now, if you want to talk about new, GraphQL is the newest kid in town (I mean, it’s been out since 2015, but it’s still the hottest thing around, you know?).

While REST focuses on resources and provides a set of endpoints around them to allow for multiple operations, GraphQL focuses on the data. It is more a query language than an actual API, although it does provide all the required tools to access the queried data as well.

Don’t let the name fool you though, it’s not a graph database like Neo4J is, instead its major benefit is that it allows you to query and request the exact data you need. This can be a major benefit over REST, where you’d had to query multiple resources, get extra properties you weren’t really looking for and then mix it as part of the client logic.

Imagine having a simple API around a blog, with users, their posts and their followers. If you wanted to get the posts from one particular user, their name and the last 5 followers, you’d have to do something like this with REST:

//#1. Get user name
GET /users/<ID>
/**
{
"id": "123",
"name": "Fernando Doglio",
"birthdate": "1983-10-24",
"address": {
"city": "Madrid",
"country": "Spain"
},
"phonenumber": 998392839
}
*/
//#2. Get user's posts
GET /users/<ID>/posts
/**
[{
"id": 1,
"user_id": "123",
"title": "Post #1",
"post_date": "2021-06-28",
"body": "...."
}
...
]
*/
//#3. Get last 5 followers for user
GET /users/<ID>/followers?orderBy=follow_date&desc=1&limit=5
/**
[{
"id": 1,
"user_id": "123",
"name": "Follower 1",
"follow_date": "2020-01-02",
},
{
"id": 2,
"user_id": "123",
"name": "Follower 2",
"follow_date": "2019-12-02",
}
...
]
*/

Notice there are 3 requests, and a lot of data I never mentioned as part of the ask (for instance, the user’s address nor the posts’ body). Now, it’s your client’s responsibility to discard the information it doesn’t need and then, mix everything together into a single object (or whatever data structure it may need).

Instead, if you were to perform the same query using GraphQL, you’d only have to do one single request that looks like this:

query {
User (id: "123"){
name
posts {
title
post_date
}
followers (last: 5) {
name
}
}
}

One single POST request with that information, we get all the data we need and because of how GraphQL works, the structure of the response will mimic that of the request. So we’ll get:

{
"data": {
"User": {
"name": "Fernando Doglio",
"posts": [{
"title": "Post #1",
"post_date": "2021-06-28"
}
...
],
"followers": [
{ "name": "Follower #1" },
{ "name": "Follower #2" }
]
}
}
}

As you can see, we’ve saved a lot of time only transferring the data we actually need and the client doesn’t have to do anything else, given the response is already formatted by the server.

This is especially helpful if you’re on a restricted network and need to take into consideration the cost of transferring data through the wire, like you would on a mobile device.

Another major benefit of GraphQL over REST is that you can get real-time updates from the server on specific events. This is usually done through a WebSocket connection, but it’s something that you could only dream about with REST.

This allows the communication to start on the server-side, instead of us having to code a polling mechanism on the client to get the new data as soon as we could (which does not mean as soon as it was accessible). This polling mechanism was also very bad for network traffic, given you’d be sending multiple HTTP Requests that would not yield any results.

Overall GraphQL is a major jump forward when it comes to data-intensive APIs because it helps optimize resource utilization. However, if your API is rather simple or is not meant to serve data-heavy use cases, going with GraphQL instead of REST could be overkill. Make sure that if you force GraphQL on your clients, they’ll be able to properly benefit from most of its features.

RPC

To close the list, I wanted to cover this old but goodie technique. It’s called RPC or Remote Procedure Call and it consists of allowing client code to call a piece of server code as if it was local.

In other words, the client is abstracted from the fact that the code used is not local, how to contact it and what happens with the data between each endpoint. Instead you just perform the call like you would with a local dependency.

Unlike GraphQL which was very data-centric and REST which is very resource-centric, RCP is more about action. What do you need to do? That’s the main question you ask when you build an RPC API.

If you want to look at an example, I built an RPC library in JavaScript for another article, you can check it out here:

Writing an RPC library in Node.js

But the gist of it is that I have a public definition of my API’s methods (which is essentially a WSDL-like file) and the client application will take that definition and create a set of methods during execution time, to mimic a local behavior, although the actual logic is remote.

From the example in that article, this is what you’d see as a client of that RPC API:

The example is simple, but a few things are happening:

  1. The client library is being instantiated and given a host and port values. This is where the client will download the API definition from and will use it to dynamically define the correct methods.
  2. The client will trigger a ready event once it’s finished reading the definition and adding the methods. This means it’s ready to be used.
  3. We’re now calling the new method on line 15. This method could be doing anything really, but here it’s just adding 2 numbers. The key though, is that the logic for adding those numbers isn’t on the client, but rather, on the remote server.

We’re transferring data through the wire back and forth, and thanks to the defined schema from the server, we’re able to correctly send and parse back types.

Notice how the actual transfer channel and protocol were completely hidden from the client. We could’ve been using sockets for all you care, the result would’ve been the same. And that is one of the major benefits of RPC over REST, you hide the channel because your focus is the action, that’s it.

Granted, with REST you don’t need a schema defining the API, in theory, self-discovery is an option. However, that definition is required to provide the abstracted experience I just mentioned, especially in typed languages, so consider it definitely not a waste of time or resources.

Sometimes we tend to have APIs that are very action-heavy and we try to force REST onto them, by coming up with abstract resources and assigning functions around them. Instead, consider that REST might not be the best solution for your problem, and try to use something else, like RPC which is a perfect match for such a situation.

What is your favorite REST alternative? Do you have one or are you a through and through kind of dev?

Have I left one out of the list? Leave a comment and share your thoughts on REST alternatives.

Develop & share JS components with Bit

Bit is an ultra-extensible tool that lets you create truly modular applications with independently authored, source-controlled, and maintained components.

Use it to build modular apps & design systems, author and deliver micro frontends, or simply share components between applications.

An independently source-controlled and shared “card” component (on the right, its dependency graph, auto-generated by Bit)

Bit: The platform for the modular web

Learn More


Not All Microservices Need to Be REST — 3 Alternatives to the Classic was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


Print Share Comment Cite Upload Translate
APA
Fernando Doglio | Sciencx (2024-03-29T09:01:10+00:00) » Not All Microservices Need to Be REST — 3 Alternatives to the Classic. Retrieved from https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/.
MLA
" » Not All Microservices Need to Be REST — 3 Alternatives to the Classic." Fernando Doglio | Sciencx - Wednesday June 30, 2021, https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/
HARVARD
Fernando Doglio | Sciencx Wednesday June 30, 2021 » Not All Microservices Need to Be REST — 3 Alternatives to the Classic., viewed 2024-03-29T09:01:10+00:00,<https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/>
VANCOUVER
Fernando Doglio | Sciencx - » Not All Microservices Need to Be REST — 3 Alternatives to the Classic. [Internet]. [Accessed 2024-03-29T09:01:10+00:00]. Available from: https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/
CHICAGO
" » Not All Microservices Need to Be REST — 3 Alternatives to the Classic." Fernando Doglio | Sciencx - Accessed 2024-03-29T09:01:10+00:00. https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/
IEEE
" » Not All Microservices Need to Be REST — 3 Alternatives to the Classic." Fernando Doglio | Sciencx [Online]. Available: https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/. [Accessed: 2024-03-29T09:01:10+00:00]
rf:citation
» Not All Microservices Need to Be REST — 3 Alternatives to the Classic | Fernando Doglio | Sciencx | https://www.scien.cx/2021/06/30/not-all-microservices-need-to-be-rest%e2%80%8a-%e2%80%8a3-alternatives-to-the-classic/ | 2024-03-29T09:01:10+00:00
https://github.com/addpipe/simple-recorderjs-demo