Samson Omojola I'm an experienced software engineer. I love creating applications with responsive, beautiful, intuitive, state-of-the-art designs. I'm skilled in HTML, CSS, JavaScript, Ionic, React, PHP, Laravel, and Flutter.

GraphQL vs. gRPC vs. REST: Choosing the right API

5 min read 1622

GraphQL Vs. GRPC Vs. REST Choosing Right API

The standard for data exchange between frontend and backend has always been a bit contentious.

With different API technologies available for sharing data between clients and servers, and each one having its own set of unique capabilities, it can be quite daunting trying to decide which one serves you best.

The three most popular technologies currently for creating APIs are GraphQL, gRPC, and REST. In this post, we’ll look at how each one works, including their pros and cons.

GraphQL

GraphlQL is a data query language that uniquely allows clients to request any specific data that they need. As opposed to REST’s HTTP methods, GraphQL uses queries, mutations, and subscriptions for sourcing and manipulating data.

Queries request data from the server while mutations send data to and modify data gated by the server. Subscriptions get live updates when data changes, usually through Websockets.

In all, GraphQL supports languages like JavaScript, Java, Python, Ruby, PHP, and more.

Representing data with schemas

With GraphQL, data is represented through schemas. A schema defines an object, the fields that the object contains, and the type of data the fields can hold. Here’s an example schema:

type User {
  name: String!
  age: Number!
}

Here, User is the object, and inside it, we specify the fields or properties the object has, including data types.

What this means is that in any query operating on the User object, the only fields that can appear are name and age. For both of these fields, the only kinds of data that can be written to or read from are strings and numbers, respectively.

In GraphQL, when field types are trailed with exclamation marks like what we have above, it means that the fields are non-nullable. They must have data written to them when the object updates and the fields always provide values when queried.

We made a custom demo for .
No really. Click here to check it out.

Defining queries, mutations, and subscriptions with schemas

As mentioned before, there are mainly three actions that can be performed on data objects: queries, mutations, and subscriptions. These can also be defined using GraphQL’s schema language.

With a query schema, you can request data from your GraphQL server by specifying the object and fields under the object you’re interested in:

query {

  users {
    name
    age
  }

}

Above, we request a list of the users in the database, specifically their names and ages. The user object could have other fields like gender or job title, for example, but only the fields we requested will be sent to us.

This is one advantage that GraphQL has over REST. In REST, when an endpoint is queried, all the data behind that endpoint is sent to you, leaving you to sort through the array and select the particular fields you need.

GraphQL is more flexible because it allows you to customize the structure of your result. This saves you the memory and CPU consumption that goes into filtering data.

And, because GraphQL queries generally request less data, they are usually processed faster than REST requests.

With a mutation schema, you can make changes to existing data or post new data to your database. For example, if you wanted to create a new user or update the details of an existing user, you’d use mutation:

mutation {

  newUser($name: name!, $age: age!) {

    name

    age

  }

}

With a subscription schema, you can subscribe to an object and have your server update your client in real-time whenever changes are made to that object.

For example, if you want your client app update in real-time whenever an existing user is deleted or modified, or a new user is created, you can subscribe to the User object and your fields of interest:

subscription User {

  newUser {
    name
    age
  }

}

GraphQL pros

With GraphQL, you can define the exact scope of data required in every instance. By preventing excess data from sending from the server to the client, your app performs better.

Since you can select multiple fields from different resources in a single query, GraphQL eliminates the need to carry out multiple round trips to the server to fetch data for your client.

GraphQL cons

GraphQL has some serious caching problems (specifically HTTP caching) that have contributed to the prevention of its widespread adoption.

Due to the way GraphQL queries are written, requesting too many nested fields at once can lead to circular queries and crash your server. Implementing rate-limiting in REST is more seamless.

GraphQL also doesn’t support file upload out of the box and requires a workaround to implement this functionality.

And finally, compared to REST, GraphQL has a steeper learning curve.

REST

The most popular and most used API format on the list is REST, which stands for representational state transfer.

REST APIs use HTTP methods like GET, POST, PUT, and DELETE to access and manipulate data within uniform resource identifiers (URIs):

  • GET methods retrieve data from a server
  • POST methods transfer data from the client to the server
  • PUT methods modify data in the server
  • DELETE methods erase data in the server.

When in use, for example, a GET request can perform on a URI that typically looks like /api/users; a REST operation typically returns data from the server to the client.

The REST response data can then come in formats like JSON, CSV, XML, or RSS, and the REST response data tends to come in property/value pairs:

{
  "users": {
    {
      "id": "1",
      "name": "Dan",
      "age": "20"
    },
    {
      "id": "2",
      "name": "Kim",
      "age": "19"
    }
  }
}

REST pros

Caching is easy in REST because it takes advantage of HTTP by eliminating the need for your client and server to constantly interact with each other, improving performance and scalability.

REST’s maturity in the tech world is one of its biggest advantages. It is ubiquitous, as opposed to GraphQL and gRPC, which can be considered niche solutions to creating APIs.

Due to REST’s popularity, lots of developers are already familiar with it and find it easy to work with. And so, if you create a commercial API for many third-party developers to consume, then REST might be the best option for you.

REST cons

Large payloads; where you can select specific fields under a resource in GraphQL, REST requires you to request all the data under the resource before looping through it to get the data you need, which often results in large payloads.

While with GraphQL we can batch different resource requests and send them to the same endpoint at /graphql, and executed once in one round trip, with REST, different requests must be sent to different endpoints, resulting in multiple round trips.

GraphQL makes making changes to a database schema very easy. Since queries only involve requesting specific fields, new fields can be removed from a resource without causing breaking changes and requiring you to version your application.

gRPC also comes with its own backward compatibility features that make it easy to update your data structure without breaking clients’ code. REST does not come with this flexibility.

gRPC

gRPC is a high-performance, open source remote procedural call (RPC) framework created by Google.

In gRPC, protocol buffers make API requests to the server. These API requests and responses are protocol buffer messages, and each one must have its own type defined using the protocol buffers language.

Services are defined to pair API requests with their corresponding responses, and the protocol buffers compiler generates the server and client code artifacts for your API service:

// Syntax version
syntax = "proto3";

service UserService {
    rpc GetUser (UserRequest) returns (UserResponse);
}

// Message type
message UserResponse {
    string name = 1;
    string age = 2;
}

message UserRequest {
    string name = 1;
    string age = 2;
}

In the code block above, the message UserRequest is the request, the message UserResponse is the response, and GetUser is the API endpoint.

gRPC supports a host of languages and your client app can be written in any of these languages because the client code for any of these languages can be generated with the help of the protoc tool.

gRPC pros

Protocol buffers, which gRPC comes out of the box with, support more data types than JSON, and it’s significantly faster, thanks to its optimized binary format.

gRPC supports full-duplex streaming out of the box, which makes it suitable for features like video and voice calls. With REST on the other hand, queries are handled one at a time.

gRPC performs load balancing so that client requests are evenly distributed across servers to avoid overloading a particular server. This improves the overall performance of your application.

The load balancing feature, as well as the fact that gRPC uses HTTP2 by default, makes latency in gRPC much lower than in REST APIs.

Finally, gRPC serializes data in binary format (protocol buffers), which is much faster than REST’s JSON, giving gRPC a greater performance advantage.

gRPC cons

Protocol buffers, gRPC’s official data format, currently only supports a handful of languages. It doesn’t support languages like R and Swift. JSON, which REST uses, is supported by virtually all languages.

gRPC doesn’t come with browser support out of the box, although there are some workarounds for it.

Conclusion

At the end of the day, the best API technology for your specific project will depend on what you are trying to achieve. If you need a generic API that will be used by a lot of clients, then REST might be your best option.

If you need a flexible API that different clients will use to make many unique requests, then it might be best to let the clients create their own unique queries and get only the specific data they need quickly, and you can achieve this with GraphQL.

If want to create fast, seamless communication between internal services, then gRPC is your best option.

As we’ve seen, all three have their pros and cons and you can get optimal results by combining technologies.

Monitor failed and slow GraphQL requests in production

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Samson Omojola I'm an experienced software engineer. I love creating applications with responsive, beautiful, intuitive, state-of-the-art designs. I'm skilled in HTML, CSS, JavaScript, Ionic, React, PHP, Laravel, and Flutter.

4 Replies to “GraphQL vs. gRPC vs. REST: Choosing the right API”

  1. Your description of REST cons is a good example of some common misconceptions about REST APIs. This largely stems, I think, from thinking of resources as rows/documents in your database… and this just is not the case.

    I’m not aware of anything in the REST specification that requires full transmission of a resource or even all the resources when you GET a REST endpoint. Plus any REST API I’ve worked with allows you to use “fields” and “query” query parameters to filter how many resources and how much of each resource is returned. Some APIs even default to only returning the id and an e-tag for the resource which you can later use for optimistic locking requests… and you can’t really ask for a smaller payload than that.

    Further, versioning a REST API because of fields being added isn’t necessary. You can always add information without re-versioning because the consuming code is already ignorant of it. It’s only when you remove fields where this is a problem. Or you just create a new endpoint with the new “version” of the resource and add another link in your HATEOAS that will allow applications to grab that instead.

    And lastly, I fail to see how having many vs a single endpoint affect batch processing unless you are needing to have atomicity. But even then, this can be resolved by creating a new REST endpoint that represents the collection of batch requests to the server. You make a single POST there that contains the information required to process the request, and then a GET against that endpoint can return the status of the request while PUT, PATCH and DELETE could be used to modify the request of delete it if the server has not begun processing it yet.

  2. My question to you is…. Did you check out Ankr’s api toolkit and public RPC protocol before you did this article??? Im not affiliated with Ankr but their products are top notch…

  3. There are some serious “assumptions” made here. Caching, for one, seems to be thought of a good thing and, while it is in some cases, it is the very first thing disabled (e.g. when access control is needed) in others and/or being only a necessary evil to make the thing perform acceptably (usually with REST). This also assumes a trivial implementation of GraphQL without any of the advanced frameworks, many of which are available. GraphQL requests cannot be circular and deep repetitive requests actually benefit from server-side query optimization available in those frameworks and server-side transaction caches even if we ignore any others. Think what would happen if you needed the same data with REST… hint: worse, much, much worse). Finally, the learning curve: I will claim that GraphQL, due to embedded documentation, standardization and tooling is much easier to learn for API users than any other. REST is absolutely the worst of all. On the server side, implementing GraphQL properly isn’t easy and requires some investment – explaining the common misconceptions. But REST is horrible in its own way as, no, NO, not everything is or should be a “resource”. There are actions, different kind of mutations, notifications all of which are horribly represented in REST (they aren’t really).

    1. It doesn’t come across to me like you’re judging REST fairly here. I totally believe what you’re saying reflects your experience with REST APIs, but REST is such a buzzword that anyone using an HTTP API calls it a REST or RESTful API when it either doesn’t conform to the standard or uses it too narrowly as a simple CRUD wrapper over a database.

      For example, we use REST to model actions and all sorts of mutations in our API to the point where we rarely, if ever, use verbs outside of GET and POST. Every type of action has a corresponding collection of actions against its base resource. Like /protocols/:id/submissions would be a collection of all the submission actions requested against a particular protocol. We practice CQRS so a POST against that collection causes our domain to decide whether or not to accept the command, and if it does, the protocol aggregate makes the appropriate state changes and persists them to the database.

      So yeah, if an API architect is trying to shoehorn every kind of activity into the HTTP verbs against a single /protocols/:id endpoint, then sure: actions, mutations and notifications aren’t represented well if at all. But they are in our REST API just fine. Well, not notifications, but that’s because we don’t have a use case to allow an external application to manually trigger them… we have an internal RxJS event stream that notification listeners subscribe to which in turn generate notifications when particular events occur.

      Also revisiting the learning curve issue: a proper REST API implements HATEOAS. That means that you should be able to give a user a single entry-point endpoint, and once they GET against that, you are told exactly what you can do via hypermedia. All appropriate actions with their endpoints and HTTP verbs allowed are returned along with any payloads.

      For us, this allows our API to completely drive what is displayed on our front end apps because if something isn’t authorized due to security or just the workflow state, the URL for the resource isn’t returned so the front end doesn’t even have the knowledge of how to make the request at all. The only thing the app has to know is 1) the entrypoint and 2) the link structure. We can change the entire structure of our endpoints so long as the link structure remains the same so we achieve pretty minimal coupling.

      But here’s the point: a properly constructed REST API should mean that all a human needs is the entrypoint. From there, you can just sit there with Postman and navigate through and explore the API with the information you get back… even completing business workflows and what not. You’ll need additional documentation for any payload requirements, but from what I understand, you need to have some idea of the schema a GraphQL server is running to run your mutations so I don’t see these as particularly distinct learning curves. And if you’re experience is that there is a big difference, again, I’d imagine it’s related to poor implementation on the REST side… which could be an argument in favor of GraphQL. Maybe it’s just harder to create a functional, yet difficult to understand GraphQL API, whereas it’s easy enough to make something awful “look” like a REST API.

Leave a Reply