API Showdown: REST vs GraphQL vs gRPC
As a decision maker for your new project, which API technology would you choose? REST or GraphQl or gRPC? Is gRPC the de-facto API style now? Time to say goodbye to GraphQL or REST? Let’s figure out.
REST
The term representational state transfer was introduced and defined in 2000 by Roy Fielding in his doctoral dissertation. The term is intended to evoke an image of how a well-designed Web application behaves: it is a network of Web resources (a virtual state machine) where the user advances through the application by selecting links (e.g. http://www.example.com/articles/21), resulting in the next resource’s representation (the next application state) being transferred to the client and rendered for the user.
The REST architectural style is designed for network-based applications, specifically client-server applications. The client requests a resource using a URI and the server responds with a representation of the resource.
The REST architectural style defines 6 guiding constraints for a system to be recognized as RESTful. When these constraints are applied to the system architecture, it gains desirable non-functional properties, such as performance, scalability, simplicity, modifiability, visibility, portability, and reliability.
1. Client–server architecture
Separation of concerns is the principle behind the client-server constraints. This improves the portability of the user interface across multiple platforms and scalability by simplifying the server components.
2. Statelessness
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. This property of stateless protocols makes them ideal in high volume applications.
3. Cacheability
As on the World Wide Web, clients and intermediaries can cache responses. Responses must, implicitly or explicitly, define themselves as either cacheable or non-cacheable. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.
4. Layered system
A client cannot ordinarily tell whether it is connected directly to the end server or to an intermediary(for example, proxy or load balancer) along the way. Intermediary servers can improve system scalability by enabling load balancing and shared caches. Also, security can be added as a layer on top of the web services, separating business logic from security logic.
5. Code on demand (optional)
REST allows client functionality to 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. Allowing features to be downloaded after deployment improves system extensibility.
6. Uniform interface
By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved. Implementations are decoupled from the services they provide, which encourages independent evolvability.
The trade-off, though, is that a uniform interface degrades efficiency, since information is transferred in a standardized form rather than one which is specific to an application’s needs.
When is REST right for you?
- When the message format maybe JSON or XML.
- The results need to cached. Since a REST API provides many endpoints, you can easily configure a web cache to match certain URL patterns, HTTP methods, or specific resources.
- Error handling in REST is easier. RESTful APIs follow the HTTP spec with regards to resources and returns various HTTP states(Ex: 200 for OK) for various API request states.
- REST can do much of what can be done using GraphQL or gRPC although there’re benefits when the other technologies are used in certain situations.
When is REST wrong for you?
For event driven and asynchronous use cases, you can use webhooks, over REST, but there‘ll be scope for you to optimize better with a purely asynchronous protocol.
Think about a scenario where you have user facing application built on microservices model that crunches a lot of data. This is where you’ll be pushing a lot of data to your big data or analytics systems and you don’t necessarily want to push through a REST API. gRPC can be your saviour for server to server communication.
Also when you want to expose all of the data through a single endpoint that is flexible which what GraphQL does.
GraphQL
GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data. GraphQL was developed internally by Facebook in 2012 before being publicly released in 2015.
Imagine if you had to design a system that showed feed similar to that of Facebook or Twitter. How would you do it? Answer: GraphQL.
The first ever implementation of GraphQL was the Facebook mobile newsfeed API. The fresh idea that GraphQL brought to the table was really thinking about data in terms of a graph instead of multiple endpoints. Unlike REST APIs, which expose data via multiple different endpoints, GraphQL exposes all of the data through a single endpoint that is flexible.
When you build a GraphQL API, you’re really trying to build a unified data graph, which client developers can then query a subset of based on what their needs are.
When is GraphQL right for you?
- In the case you a web application and a mobile application, that access the same set of data but the view looks different in both.
- When you have multiple data sources for a single application, and you want to streamline those into a single interface.
Say you’re building a client application, and it has loads of data sources, say like, three REST APIs, a JSON file, and a database. Maybe one of those REST APIs is a horrible legacy API that people are scared to touch, and it’s undocumented, and the naming is horrible. You can’t really change anything in it because it has to remain backwards compatible for other applications. In this case, you have disparate data sources and GraphQL is the perfect tool for the job to unite those data sources in a data layer. You can wrap all of them in a single GraphQL layer
When is GraphQL wrong for you?
Lee Byron(One of the creators of GraphQL), has said in the past that GraphQL really isn’t the right choice for server to server communication.
As we know GraphQL exposes only one endpoint and by simple logic someone might think the results might not be cacheable, well you’re wrong. https://youtu.be/LY_vMCjuC5M
I’ll not be commenting on what is easier to learn or how complex it is as that can also depend on a person’s past experience.
gRPC
But first what is gRPC?
gRPC Remote Procedure Calls, of course! (Link)
gRPC is just a new version of Stubby, the API technology Google used internally for a long time, for over a decade. This new version is based on HTTP/2 and is now used in many organizations outside of Google to power use cases from microservices to the “last mile” of computing (mobile, web, and Internet of Things). It uses HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control, blocking or nonblocking bindings, and cancellation and timeouts. It generates cross-platform client and server bindings for many languages(really useful).
One of the ideas was to bring all those performance improvements and capabilities of HTTP/2 into a simple, performant, easy-to-use API first framework that can be utilized in a number of scenarios, from high throughput backends to communication with devices on unstable mobile networks, with limited CPU and memory footprint.
When is gRPC right for you?
- If you’re designing a low-latency, highly scalable distributed system. The default out of the box implementation is using protocol buffers as an ideal and serialization mechanism.
Protobufs are wire efficient and are more than a serialized format. They include three other major parts:
a. A contract definition language found in.proto
files.
b. Generated accessor-function code
c. Language-specific runtime libraries
If your backend is used by mobile clients, they will be more tolerant to bad network connections because you just send less data over the wire. Those clients will need to spend less CPU on deserialisation, which helps with battery life. - If you’re building a backend system that includes hundreds or thousands of interconnected microservices, gRPC will offer efficiency and speed, and also will provide built-in features like deadline propagation, cascading cancellations, retries, request hedging, and so on.
- If your complexity is in QPS, throughput, latencies, you’re concerned about optimizing tail latencies, go with gRPC.
- If you will need streaming APIs. Your application needs to stream multiple requests or multiple responses in one RPC interaction. For example, data from sensors or stock price and sub-millisecond latency. You may need flow control or backpressure for those streaming APIs. Streaming RPCs with flow control have first class support in gRPC.
- If you need TLS, load balancing, custom authorization, monitoring.
gRPC provides building blocks with default implementations and extension points for all those concepts. You can give it a try just for expressive language-neutral ideal, and auto-generated client libraries, and later start using those additional features and extensions when you need them.
When is gRPC wrong for you?
- When your language is not supported. Code generation comes with the downside that only 11 languages are supported.
In case your consumers cannot use or don’t want to use a language that is supported, you can create reverse proxies (refer projects like gRPC gateways). It creates REST endpoints for gRPC services, or you can use Envoy with gRPC-JSON transcoders that translates RESTful requests into gRPC. But these are workarounds at the end of day and won’t be so efficient. - If you’re building a migration API or an API that will sunset soon, the schema overhead might not be worth it.
- When you’re building a service that only talks to a web browser, and it doesn’t call any backend services, it just calls the database, or you’re building a monolith for a good reason, in those scenarios, you can get more benefits from another technology, GraphQL or REST. Yes, you may still be able to use gRPC.
- To talk to the web browser, you will need gRPC web proxy, and communication between proxy and the web browser will still be HTTP/1.1. If your only integration point is web browser, gRPC is probably not the best choice.
- When you have rich UI application that pulls data from dozens of services, GraphQL can be the better choice.
As per the latest Google trends, REST still leads the way for new/experienced developer’s searches.
TL;DR
Choose
- GraphQL if you need something that pulls data from various sources or if you need capability to show different sets of data(in case of different clients but for same set of data).
- gRPC if you want a highly performant server to server capabilities that leverages HTTP2.0.
- REST for everything else.
References:
- https://www.infoq.com/presentations/rest-graphql-grpc/
- https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
- https://en.wikipedia.org/wiki/Representational_state_transfer
- https://www.rfc-editor.org/rfc/rfc7231
- https://graphql.org/
- https://en.wikipedia.org/wiki/GRPC
- https://youtu.be/LY_vMCjuC5M
- https://blog.logrocket.com/graphql-vs-rest-api-why-you-shouldnt-use-graphql/
- https://www.toptal.com/grpc/grpc-vs-rest-api#:~:text=REST%20APIs%20generally%20use%20JSON,than%20those%20of%20REST%20APIs.
- https://trends.google.com/trends/explore?date=today%205-y&q=gRPC,REST%20API,%2Fg%2F11cn3w0w9t