Why and How GraphQL Is The Best Tool For Efficient Data Fetching- GO Tech Blog


Just recently our GO Dev team embarked on a project to integrate Monday.com cloud service to one of our internal components. Their API was GraphQL and that's why we came to work with this technology.

GraphQL is an API standard that provides a more efficient, powerful and flexible alternative to REST. It was developed and open-sourced by Facebook. At its core, GraphQL enables declarative data fetching where a client can specify exactly what data he needs from an API. Instead of multiple endpoints that return fixed data structures, a GraphQL server exposes only a single endpoint and responds precisely with the data the client asked for.

In this technical article we will explain the what, why, and how you can use GraphQL based on our recent experience. 

GraphQL vs REST

GraphQL was developed to cope with the need of more flexibility and efficiency. It solves many of the shortcomings and inefficiencies that developers experience when interacting with REST APIs.

Data Fetching

Let us assume a scenario where an application needs to access information on a user, his posts and his followers in a blogging database. To be more specific, the client wants to get a particular user name, all the titles of his posts, and the name of his followers, possibly limiting the amount returned.

With a typical REST API, you would gather the data by accessing multiple endpoints. Here the client first called the "users" endpoint to get the name of user "USER_001". The second call was to the "posts" endpoint to get the titles of all posts posted by "USER_001’', and finally a last call to the "followers" endpoint return the followers of the user (see Figure 1).

Figure 1
Immediately we see two major problems when dealing with a REST API:

  1. Accessing multiple endpoints to gather the desired data. Three requests were made to fetch the data. Each request added to the network traffic and overhead, and thus increasing the possibility of network latency.
  2. Over-fetching or under-fetching. Over-fetching happens because the only way for a client to download data is by hitting endpoints that return fixed data structures. Under-fetching is when a specific endpoint doesn’t provide enough of the required information.

All the three requests returned data that was not needed by the client. The user id and address, the posts content, and the followers’ id and address were returned in the rigid response, and discarded by the client. Nevertheless this was data that was transferred over the network.  

The above problems raise from the inflexible nature of the typical REST API.

Now let us see the flow of the same scenario when using a typical GraphQL API. In this case (see Figure 2) we only need one endpoint. One single request is sent to the server that includes a query with the concrete data requirements. The server responds with a JSON object which represents the exact data that was specified in the query requirements. The server is responsible for parsing the query and mapping it to the backend data. 

Clearly here we see the flexible nature of the GraphQL API:
Figure 2
  1. Accessing a single endpoint to gather the desired data. One request was made to fetch the data. No extra network traffic and overhead.
  2. No over-fetching or under-fetching. The client specified exactly the data that was needed. In this example, only the name of a specific user was returned, along with the title of his posts and the names of his last 3 followers, as requested by the client. No extra data was transferred over the network.  
  3. Insightful analytics on the server. As the client specifies exactly what information it needs, it is possible to gain a deep understanding of how the available data is being used. This can, for example, help in evolving an API and remove certain functionality that is no longer needed.
Taking a closer look at the GraphQL query in our scenario, we can see from a conceptual view the following: 
So far so good; but how does the client know which data can it queries from the API? This is done by the schema, which defines what objects and fields the client can query. The schema is defined by the API and exposed to the client. Objects in the schema are related to each other using the graph model, where data is organized as nodes, relationships, and properties (more on this in the next section)

From the above, we see 3 very important concepts of GraphQL:



The GraphQL Schema - a closer look

The schema is one of the most important concepts when working with a GraphQL API. It is often seen
as a contract between the server and the client. It specifies the capabilities of the API and defines how clients can request the data. It defines the server API, allowing clients to know which operations can be performed by the server.

The schema is written using the GraphQL schema language (also called Schema Definition Language, SDL). With it you can define object types and fields to represent data that can be retrieved from the API as well as root types that define the group of operations that the API allows. 

The root types are the entry points to the API and are split in the Query type, Mutation type, and Subscription type, which are the three types of operations that you can run on a GraphQL server. The query type is compulsory for any GraphQL schema, and the other two are optional. Although you can define custom types in the schema, the GraphQL specification also defines a set of built-in scalar types called the primitives, which are Int, Float, Boolean, String, and ID. The data in the schema is graph-modelled.

A schema for the blogging scenario mentioned above could be contextually viewed as:

Relation type between objects can be one-to-many or one-to-one. The important things to remember about the schema are:
  1. Objects are made up of primitive and/or other objects.
  2. Access to the API is ONLY through the root types, which define the operations of the API. 
  3. The root types are objects themselves.
  4. Following from 3, a request to the server reduce itself to just defining the fields of an object that are required.
  5. Objects are linked together through their relation. Thus a single query request can fetch any data from the schema. For example, starting from the "query" object, you can also access the users, and since the "user" has a relationship or is related to both "post" and "follower" you can also fetch these.
  6. The object can accept arguments in GraphQL. Arguments serve the same purpose as your traditional query parameters or URL segments in a REST API. You can pass them into the query fields of an object to specify how the server should respond to a request. Arguments can be mandatory or optional. 
In the scenario mentioned earlier, we used the argument "last" when in the query we were defining the followers. 


The "last" argument instructs the server to only return the last 3 followers for that user. Thus the schema for our blog scenario, using the GraphQL SDL would look something like this: 

Client Query examples using the schema

Here are some queries that we would be able to send to the server with the above schema: 


The GraphQL Schema - a server perspective

Figure 4
At this point we are mostly covered from the client side with regards to the schema, but what about the server side? The client is sending queries and receiving requested data, but the server needs to do the dirty work to fetch the actual data.

The GraphQL server has 3 major components (see figure 4): The Schema, The Parser and The Resolver.  

The Schema as we have already seen, defines what objects and fields the client can query. This is the contract with the user.

The Parser function is twofold:
  1. Query Validation. Once a query is received from the client, the parser will match the object in the query with the schema. If the object type and the types of its fields do not match with the schema, then this will result in an error response. If the validation is successful, it goes to step 2.
  2. Query parsing and response building. Here the parser will iterate on each object and field type inside the query and for each type it will call a "resolver function" to get the data for that type. The "resolver function" is part of the resolver component. Note that the parser has no knowledge how to fetch the data, it just maps each "type" to a "resolver function". It is the "resolver function" which is responsible to fetch the data and pass it back to the parser.
Once the parser has called all "resolver functions" for each type, and has all the data at hand it will then build the response and send it back to the client.

The Resolver contains the functions which fetch the actual data. The sole purpose of a resolver function is to fetch the data for its field. Once all resolver functions are returned, the server will package data up in the format that was described by the query and send it back to the client.

Note that the resolver can call any interface to get the data. As shown in figure 4, it can access any database type and can even call a REST API.   

GraphQL over HTTP

Figure 5 below shows how GraphQL is typically transferred over the HTTP protocol:  
Figure 5


Note that the GraphQL query is not JSON; it looks like the shape of the JSON you want. So when we make a 'POST' request to send our GraphQL query to the server, it is sent as a "string" by the client.
The server gets the JSON object and extracts the query string. The server returns the data as a JSON object.


If an error occurs on the server the response will contain a list of errors the client can parse. 

GraphQL @ GO

Recently at GO we wanted to bridge the link between Customer Care Agents and the CMU (Cable Maintenance Unit) Team, making the process of information sharing more efficient.

This resulted in our customer facing employees having direct visibility with regards to cables and maintenance works.

The project involved the integration between the Salesforce platform and the Monday cloud service. 


Conclusion  

Let’s have a closer look at the main differences between GraphQL and Rest:


We hope this article has given you a lot of information on how GraphQL can benefit your business and processes. The main reasons we are using this new tool can be summarised:







About the Author and the Team

Gerald is a Software Developer within the Digital Team of GO, with 30 years of experience. With his colleagues they are the wizards who focus on the fibre logical network inventory re-engineering.

Check our current vacancies and join our team!

Comments

Popular posts from this blog

Rebooting your mindset. From assignment all-nighters, to days at the office.

And there you were, thinking Engineering is just for men. Well, think again.

Nobody likes a Negative Nancy – So here’s how not to be one!