Getting started with GraphQL

Apr 4, 2022by, Shawn S Thottan

Uncategorized

REST APIs have been the ‘go-to’ method for client-server communication for a long time now. With REST, everything is about accessing resources with specific URLs. Each API calls a different function in the backend which in turn call different data access objects. Each request goes through specific routes to access its resources. GraphQL tries to change just that. It tries to create a more generalized route that would be shared by the requests. This means that the developer doesn’t have to spend his time writing CRUD operations for every model in the project. With GraphQL all the four operations can be done with minor adjustments on a single query.

Introducing GraphQL
GraphQL is an open source querying language created by Facebook. It is a query language for APIs and server-side runtime execution. It is considered to be an alternative to REST.
The three main components of GraphQL are:

  • Query
    Queries are sent by the client. It specifies the requirements for the data to be returned from the server. Queries have to follow the guidelines provided by schemas. Queries make GraphQL special by retrieving data that is required by the client. Nothing more, nothing less. Only the data required by the client is sent from the server. The response of a query is highly predictable to the client as the query provides the structure of the response.
    The two main types of queries are query and mutation. A query is used to retrieve data and mutations are used to modify data. It’s a conventional practice to avoid mixing the two types of operations. Besides queries and mutations, there are also subscriptions which are used to receive updates from the server when some event occurs. Subscriptions are done the same way as queries and mutations. The difference is in the response times.
  • Schema
    Schemas are data structures that are used as a reference to send queries. Schemas are defined in the backend. The client only uses the schemas to form the queries. Any data requested by the query has to be specified in the schema.
  • Resolver
    Resolvers are used in the backend to specify what is to be done when a query is made. The operations on the data are performed by the resolver and the data requested is returned here.

REST vs. GraphQL

What if we are trying to create an API using REST that would return user details. Let’s start by creating a REST API to return the name of a user with the ID we provide. There would definitely be a resource function and a data access object. If we wanted another API to return the address of the user with an ID, we’d have to create another resource function and another data access object.
So now there are two API endpoints,

/user/name/<id>
/user/address/<id>

What if we were trying to do the same with GraphQL?
We’d start off by creating a schema, which is the model of the data. It represents the structure of the data.

A sample schema would be:

schema {
  query: Query
  mutation: Mutation
}

type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
  address: String!
}

The queries sent from the client side has to be recognized by the server-side schema. In the schema presented above, a single query is defined that takes in an argument value ID. So the ground rules for the query is set. It has to have the name user and the argument id. The selected fields can vary according to the requirements.

Next, we’d have to write the resolver function which defines what is to be returned. Our resolver would be,

Query: {
  human(obj, args, context, info) {
    return context.db.userByID(args.id).then(
      userData => new User(userData)
    )
  }
}


GraphQL only uses a single endpoint.
/graphql

The queries for both the requests would be like,

query {
  user(id: “2000”) {
    name
  }
}

 

query {
  user(id: “2000”) {
   address
  }
}


From the looks of it having two different APIs doesn’t seem much of an issue. It does look like GraphQL makes things unnecessarily complex. But, what if there were hundreds of APIs, then surely this could have a role in reducing the complexity exponentially.

Why you should be using GraphQL

  1. Simplicity was the keyword behind developing GraphQL, or at least I would assume so. There are ways to achieve the things that GraphQL does, using REST APIs. It would just require much more effort and a colossal amount of time. For starters, GraphQL exposes only a single endpoint. Every single request has the same specifications. The only thing that differs is the query itself. It reduces the headache of matching all the APIs as per the documentation. Better yet, from the backend perspective, it reduces the necessity of creating documentation at all. The schemas would provide sufficient information for the client to query.
  2. Schemas are the main components when using GraphQL. GraphQL uses a declarative approach to querying. Instead of focusing on specific APIs, we develop schemas that are a general representation of the data to be queried. If you’d want to query for the ‘name’ and ‘ID’ of a specific user at different times you can make use of the same schema called ‘user’. When using REST you would have to deal with two different APIs. Another approach would be to use a single API that would return both the ‘name’ and the ‘ID’, which brings me to my next point.
  3. You only query for what is required. The client decides on the data that needs to be received. The backend only sets borders to what can be queried. The flexibility offered by GraphQL when it comes to querying is unparalleled. In REST the client has no control over what information is being sent back. The server could be sending more than what’s required. This is called over-fetching and this does not happen when using GraphQL.
  4. A similar issue with REST is under-fetching, which is when a single API request is not sufficient to get the information needed. GraphQL supports nested queries where we are able to add more details with the same request. Since the structure of the response is decided in the frontend, under-fetching and over-fetching are issues that GraphQL managed to solve.
  5. Apart from all these, I’ve also got to give credit to GraphQL playground, an inbuilt IDE which is by default enabled and available on the same URL as the GraphQL server(/graphql). It’s enabled on development environments and makes frontend development that much easier. It supports auto-completion, error detection and provides a dictionary on the fields and types used for querying.

When not to use GraphQL
Even though GraphQL is claimed to be ‘the better REST’, it does have it’s fair share of nuisances.

  1. Error handling is a bit more ludicrous when it comes to GraphQL. The API response in itself is no help in identifying an error as it always returns the status code 200. We would have to dig through the body of the response and extract out the actual error message. The alternative would be to handle the errors in the frontend and leave very little of error handling to the GraphQL server.
  2. Another instance where GraphQL proves itself to be better avoided is on most smaller applications. Applications that require minimal APIs rather not bother with GraphQL, since it could only make things more complicated. You’d have to deal with types, queries, mutators and resolvers, and it’s just not worth it from a maintenance perspective. There has to be a threshold level of API complexity an application must cross for it to be beneficial to use GraphQL. 

    In summary, GraphQL is a neat tool that would help you simplify the process of creating and managing API calls. There are plenty of reasons to go for it. If you are trying to use it on a fairly complex project in terms of server-client communication, GraphQL is definitely recommended.