From ’00s to ’20s: migrating from RESTful to gRPC
This article is based on the talk I gave on June 21st at the API Conf 2018.

What this article is about
Roy Fielding is one of the authors of the HTTP protocol, co-author of the Apache HTTP server. Indisputably he is one of the most impactful figures in the computer networking field. In 2000 he presented the REpresentational State Transfer architecture in his doctoral dissertation. That moment marked a turning point in web development history: software engineers no longer needed to reinvent the wheel as they had a single standard to adhere to.

Unfortunately, while the foundations of the REST architecture are strong and valid, its implementations usually aren’t. Most of the available RESTful APIs do actually violate REST principles. Aim of this article is to highlight these violations and indicate the limits of the REST protocol. A couple RPC-like protocols are also presented, to provide the reader with two alternatives.
Summary:
- Before REST: a couple protocols mostly used before the switch to REST
- REST architecture overview: a quick glance at REST and its principles
- What’s wrong with REST?
- Two RPC alternatives: JSON-RPC and gRPC
Before REST
By the time REST was conceived and launched, two different software architectures were largely used: CORBA and SOAP.
CORBA (1991)
CORBA stands for Common Object Request Broker Architecture.
Such architecture is designed to enable communication between software written in different languages and running on different computers. All the implementation details are removed from the responsibility of the developers who use CORBA, as the protocol defines a standard in the method-call semantics between application objects residing either in the same application or on remote hosts. The problem with CORBA, though, is that it suffers the lack of a single design, so all the implementations of the protocol are incoherent.
SOAP (1998)
SOAP stands for Simple Object Access Protocol.
It is a messaging protocol designed to transfer objects across different web services on different hosts. It encodes data in the XML format, with the aim of providing extensibility, neutrality and independence to developers.
SOAP introduces:
- the concept of envelope, which defines the message structure and how to process it
- a set of encoding rules for expressing instances of application-defined datatypes
- a convention for representing procedure calls and responses
While potentially powerful, SOAP is often considered extremely verbose, slow (due to the use of XML) and — last but not least — it lacks a standard interaction model between applications.
REST architecture overview
According to Fielding’s dissertation, API scalability and performances can be improved with the application of the following principles:
- Software applications and their features should be arranged in web resources
- Those resources must be universally identifiable
- Those resources must be accessible via a universal interface, that is a generic and well defined way to fetch data
Quoting Fielding himself:
The design rationale behind the Web architecture can be described by an architectural style consisting of the set of constraints applied to elements within the architecture.
Elements
There are three foundation elements in REST architecture:
- Data Elements: Resources (any information that can be named, e.g. a document or image), URIs (Universal Resource Identifiers, which uniquely identify a particular resource involved in an interaction between components) and Representations (the media type representing such data in a given moment).
- Connectors: encapsulate the activities of accessing Resources and transferring Resource Representations. They present an abstract interface for component communication, enhancing simplicity by providing a clean separation of concerns and hiding the underlying implementation of Resources and communication mechanisms.
- Components: the elements which aim is to initiate, encapsulate or handle HTTP requests (e.g. user agents, origin servers, proxies or gateways).
Constraints
Starting from the core concept of the WWW, Fielding indicates the following constraints one onto another, to describe REST architecture:
- Client/Server: that is to separate the user interface from the data storage, to improve the portability of the user interface across multiple platforms and improve scalability by simplifying the server components.
- Stateless: each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server.
- Cache: to require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
- Uniform Interface: all the services expose their resources via a general interface, allowing implementations to be decoupled from the services they provide.
- Layered System: the architecture is composed of hierarchical layers by constraining component behavior such that each component cannot “see” beyond the immediate layer with which they are interacting.
- Code-On-Demand: client functionality can be extended by downloading and executing code in the form of applets or scripts. This simplifies clients by reducing the number of features required to be pre-implemented.
What’s wrong with REST?
As pointed above, REST principles and characteristics are pretty neat, so the reader would probably ask:
“OK, so what’s the problem with REST?”
The following example will help me to point out some common issues with REST.
Let’s imagine an API, e.g. api.example.com, providing a list of people.
In that scenario, the usage of the HTTP verbs on the URL https://api.example.com/persons would be:
- GET: used to retrieve the list of URIs and other details of all the person items in the database
- PUT: used to replace the entire persons dataset with a new one (massive replacement)
- PATCH: should not be used
- POST: used to add a new person object to the dataset
- DELETE: used to delete the entire persons dataset
Similarly, the usage of the HTTP verbs on the URL https://api.example.com/persons/123 would be:
- GET: used to retrieve the person object matching the given identifier “123”
- PUT: used to entirely replace the addressed person object with a new one
- PATCH: used to update the addressed person object only with the given fields
- POST: should not be used
- DELETE: used to delete the addressed person object from the dataset
As pointed out, there’s at least a case in which a specific HTTP verb should not be used. Moreover, the list of HTTP verbs mentioned above is not complete as the protocol supports more and more of them, which are often unused (OPTIONS, HEAD, TRACE, CONNECT).
To make matters worse, the list of HTTP status codes is… huge:
- INFORMATIONAL: 100, 101, 102, 103
- SUCCESS: 200, 201, 203, 204, 205, 206, 207, 208, 226
- REDIRECTION: 300, 301, 302, 303, 304, 305, 306, 307, 308
- CLIENT ERRORS: 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451
- SERVER ERRORS: 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511
- UNOFFICIAL CODES (oh yeah, we needed them — really, we did 🙄): 103, 218, 420, 450, 498, 499, 509, 530 and many more

What does ‘RESTful’ actually mean?
The amount of combinations between HTTP status codes and verbs is so high that there’s little or no agreement on how they should be used, like in this case:

Are you sure to really support REST vocabulary in your APIs?
There’s a lot of frameworks and clients which do not support all the available HTTP verbs. As a consequence, the developers implementing RESTful APIs use some tricks to avoid this issue. Take a look at the following image:

Why did Twitter developers not implement destroy and update operations using DELETE and PATCH HTTP verbs?
Well, there are different possible reasons, for example:
- Some (very old) browsers do not support some HTTP verbs
- Some company networks do actually block PUT or PATCH requests
What if I do need to think about ‘actions’?

According to Yelp API reference, a developer willing to search for businesses must execute a GET HTTP request on the https://api.yelp.com/v3/businesses/search endpoint.
The ‘search’ term isn’t actually correct as the returned response is a list of ‘business’ objects, so what’s the reason beyond this design?
There are some cases in which it is pretty difficult to combine the right HTTP verb with a specific status code.
This usually happens because REST pattern isn’t a good fit when the API being designed must support ‘actions’ or ‘operations’. This leads developers to use tricks, spreading bad habits in the ecosystem.
Moreover, in this peculiar example all the request parameters are passed via GET query attributes. As the number of used parameters increases, the readability of the requested URL gets worse.
Two RPC alternatives
JSON-RPC
Designed in 2005 (version 2.0 came in 2010, last update in 2013), JSON-RPC is a remote procedure call protocol which offers the following features:
- Stateless: as REST is, with the same PROs and CONs
- Lightweight: there’s no data nor protocol overhead as it happens using SOAP
- Transport agnostic: it can be used on HTTP as well as on different communication protocols
- JSON as data format: it uses JSON, which is pretty handy compared to XML
- Notification requests: special requests meant to be used when there’s no interest in waiting the response from the server
- Batch requests: it is possible to run multiple requests in a single batch. The server is supposed to reply to all the non-notification requests.
PROs
- Readability: JSON-RPC requests and responses are pretty straightforward to read and debug, as they are JSON objects
- Ease of encoding/decoding: for the same reason, they are also easy to implement as JSON encoders are available for any development language
- Separation from transport protocol: JSON-RPC aren’t tied to HTTP. Porting an existing API from HTTP to another protocol is a quick operation
CONs
- No binary encoding: there’s no way to support binary objects, which could be used to speed up the transfer operation
- Easy to mess up method names: there’s no standard way to name methods, BTW this could be true for any RPC implementation
The link above refers to a repository where a sample JSON-RPC client — server architecture is available. The server software is implemented in Go, while the client consuming it is written in Python.
gRPC
Initially developed at Google, gRPC is an open source Remote Procedure Call protocol . It uses HTTP/2 for transport, Protocol Buffers as the interface description language, being able to generate cross-platform client and server bindings for many languages.
Here there are some of the features it does offer:
- Built-in support for several languages: it is possible to write server/clients in a lot of programming languages (here the full list)
- Bidirectional streaming: as the protocol is recent, it natively offers support to single or bidirectional streams from and to clients
- Blocking and non-blocking: both synchronous and asynchronous operations are possible
- Lameducking: a server could be turned off without affecting the existing requests, which will be gracefully handled
- Flow control: it offers a better buffer management and the possibility to mitigate DoS attacks
- Standardized status codes: some default status codes are offered to avoid developers reinvent the wheel
PROs
- gRPC is modern: it has been designed with the actual needs of developers in mind
- Payload agnostic: protocol buffer is not the unique transport format you can use. JSON, XML and Thrift formats are supported as well
- Simple to use: as the protocol supports many languages, it is possible to implement APIs quickly
CONs
- Not suitable for web browsers (yet): this is IMHO the most important CON. A beta project is work in progress in the moment I’m writing this article
- Requires the knowledge of Protocol Buffers for designing an API
The link above refers to a repository where a sample gRPC client — server architecture is available. The server software is implemented in Go, while the client consuming it is written in Python.
Conclusions
As we have seen, REST concepts are solid.
The problem with REST, though, is the fact that it can’t be used in 100% of the cases, e.g. when using an ‘operation’ approach.
In those cases, IMHO, RPC protocols are a good choice.
You can actually take advantage of most of the REST concepts when developing RPC services, and both JSON-RPC and gRPC are two valid options to consider:
- JSON-RPC is really simple to implement and to use as a full replace of a full stack REST API
- gRPC is a powerful choice when developing APIs meant to be used in server-to-server communication
What do you think about this topic? Please let me know your thoughts!
