GraphQL – The Better REST

Reading Time: 5 minutes

Over the past few years, the REST has become a de-facto architecture for the web services, which emphasize to communicate through the textual data. The user is given a URI of the resource and user can perform various operations (GET, POST, DELETE etc) defined on that address, as simple as that. There are several architectural points that reflect upon the ideology of the REST. These points deserve a short review before we move on to the Graphql:

  1. Starting with the Null Style: When a developer starts developing a service or application, she might have an image of what she is going to create but still, she has to start from zero. She can design this application in any way, expand it with no boundaries, having the final interfaces of the application in her mind.
  2. Client-Server: The client and server implementations must be developed and flourished independently. The user interface should not be aware of the implementation of the server side services. Though there should be a mechanism through which client requests the server for some resources and get exactly what she needs. REST does this by providing the URIs.
  3. Stateless: The request from a client to server must contain the necessary information in it so that server can understand what the client needs but it should not depend on any previous information shared between the two. This is a trait inherited from the early web architecture. The modern web can store the session information on server and client sides. The request information can also be stored in the cookies.
  4. Cache: The cache on the user side can improve the network efficiency. In REST, each response can be labeled as cacheable or non-cacheable. The cached response can be used for the response of the request rather than asking the server so we can eliminate the communication between the server and client up to some degree. Though, the shortcoming of this feature is that if a server has some new information for a cached request the client might not get the updated information.
  5. Uniform Interface: Through the uniform interface of the application, the architecture of the application is simplified in a generalized manner. The application of the interface can be altered in many ways but the interface remains intact. With uniform interface, there come four constraints –
    • Resource identification in requests: The resources can be identified in requests, like with URIs in web APIs.
    • Resource manipulation through representations: The client can inform the server to perform some operations on the resource, like GET, POST, DELETE, PUT etc in web-based APIs.
    • Self-descriptive messages: The request can have the information about the message through their formats attached with the request, like MIME Types in web-based APIs.
    • Hypermedia as the engine of application state: The initial URIs given to the client to access the APIs can be used to pass the hyperlinks of more APIs available or newly created. It’s analogous to the HTML pages which include the hyperlinks to more pages available on the server. Hence it makes the APIs dynamic that can evolve over time and client can leverage that.
  6. Layered System: The REST further can be extended to build layers of the communications. There can be layer(s) which can talk to just one layer and not beyond that. It hides the details of the system implementation. In modern scenario, we can see the service locators, load balancers, proxy servers, layers within server farm etc.
  7. Code-On-Demand: The REST allows the client to get the code from the server to execute on its end. It extends our system and delegates some processing from the server to the client. Though, it’s an optional constraint of the REST architecture.

Shortcoming of REST

REST is beautiful. It might appear elegant as well. Though, it’s not really a better solution for communications always. For example, GitHub provides various APIs to be accessed publicly. One of them is https://api.github.com/users/{username} and the API returns all the public information of the user in JSON format. If we need to get the name of the company where the user is working, we can read the ‘company’ key from the JSON. But along with this JSON data, we’re also getting 28 more redundant keys. These values may not hold much significance to the API consumer, but this redundant data will be traveling from GitHub servers to the API consumers, that is there is an unnecessary load on network and API consumer (the data will be sitting in the memory of the consumer system). Besides the data transfer between systems, another problem is processing of the information. The big JSON text will still be parsed and processed by the API consumer. What we need is a better solution, that can provide the ease to access the needed data only. In our example we need is the name of the company where the user works. With REST, we can do this by creating one more REST endpoint that returns the company information of the user. One such endpoint could be https://api.github.com/users/{username}/company . That sounds like a solution to our problem! Is it really? If we have 30 fields/keys of the user information, then we need to create the 30 REST endpoints. That’s a big number of APIs to maintain (just for user information).

GraphQL – The awesome REST

GraphQL allows us to mention the fields that we want for some entity. In our example case, we can ask the server to return only the company name, if server handles the GraphQL queries.

The fun part about the REST is we get to write the queries as if we are calling the functions of a programming language. We ask the server to either process/query some data and along with that, we pass the field names which we need from the server after the server is done with it job.

One thing that would tickle one’s mind is why the architectural points of the REST were mentioned in the starting of the blog post! Well, it’s just to emphasize the point that GraphQL still follows all of that. Though, GraphQL requires the API consumer to send the requests usually in POST method (in some cases other methods like GET as well, we can pass the query encoded into the URL, but then the server needs to decode that query and process it). So, GraphQL is still REST-ish, plus the fast response from the server and less load on the networks.

The elegant part of the GraphQL is that we can use just one URI for our APIs. We can either ask the server to give some data, or process some data sent by the client or even open the stream of the data between client and server – all on the same URI. Another good part of the GraphQL is the ability to write the queries in the code-like structure. The client can write the queries that look like a function in any C-like programming language; the functions can also accept the arguments.

query findUser($userId: String!) {
  findUser(id: $userId) {
    name
  }
}

This is a simple query that asks the server to return the name of the user with id equals to userId. The userId argument can either be hard-coded in the findUser() function or it can be mentioned in the variable field of the GraphQL JSON. Wait, did I say “GraphQL JSON”? Yes, we send the graphql in JSON format to the server, wrapped in key-values; though it’s not necessary to do so, it all depends on how the server accepts the query and parses it. We, at Knoldus, use the Sangria library for Scala and all it cares about is

  1. the query (which is a mandatory field and can be the mutation or subscription or a query),
  2. the variables (it’s optional) and
  3. the operation name(it’s optional as well).

So, it’s easy to keep all these together in a JSON format.

The beginners might also want to know what are all these terms after all! The query, mutation, operation, fragment, data-types, schema, fields etc. For the brevity sake of this blog post, these terms and much more about the graphql can be explained in future blog posts.

 

Written by 

Principal Architect at Knoldus Inc