Written by Samson Omojola✏️
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.
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 added to 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.
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. Start monitoring for free.
Top comments (1)
We also did our fair benchmark with Go examples to compare Protocol Buffers over gRPC vs. JSON over HTTP/1 and HTTP/2. The results are very interesting - packagemain.tech/p/protobuf-grpc-v...