API / Programming

GraphQL and how it’s different from REST

Introduction

What exactly is REST? REpresentational State Transfer (REST) is an architectural style for implementing APIs. It uses http(s) verbs (GET, POST, PUT, DELETE) in a URL to request resources. REST is resource based. Representation of a resource is different from the actual resource. We can think of the representation of a resource as a structured access to that specific resource. For instance, in REST when you make a call to an endpoint, the API is basically structuring the response in a specific way before returning it, so what you’re getting is not the actually resource.

At first when I heard of GraphQL – and a lot of people are guilty of this misconception – I thought it was a tool for querying databases. GraphQL is a query language for APIs or a specification for how an API should interact with other parts of an application. GraphQL, developed by Facebook in 2012 and open sourced in 2015,  is an architectural style for implementing APIs. Therefore, GraphQL is simply a specification for developing flexible and efficient APIs. You might be able to argue that GraphQL is a version of REST just with more flexibility and less inefficiencies than a traditional RESTful API. One key difference between GraphQL and a traditional REST API is that in a REST API, multiple endpoints are typically used to fetch data but a GraphQL API utilizes just one endpoint and returns exactly what the user asks for (which is the key selling point of GraphQL). We will go into detail about GraphQL components, how they are implemented and the advantages as well as disadvantages of using the GraphQL architectural style.

Components/Implementation

You probably don’t have to implement GraphQL from scratch because there are many implementations in most popular programming languages that will help you setup a GraphQL framework for your project. From Java to Go. You can check out the list of implemented languages for GraphQL servers here. Let’s move on to the components of a GraphQL API. That is, what will you need to successfully implement a GraphQL API?

1.) A schema for defining the API (this is no different from swagger or at least go-swagger if you’re familiar with the Go programming language). For our example, we’ll use a fictional organizational structure and the GraphQL Schema Definition Language (SDL).

Sample GraphQL schema:

type Organization {
  id: ID!
  name: String!
  employees: [ Employee! ] !
}

type Employee {
  id: ID!
  name: String!
  duration: Int!
  position: [ Position! ] !
}

type Position {
  name: String!
  responsibility: String
}

Note: The exclamation mark “!” after a property’s type, means that property is required and cannot be empty. So for either [ Employee ! ] ! or [ Position! ] !, the array contents must be of type Employee or Position respectively (as indicated by the exclamation marks inside the square brackets). And they must be non-nullable arrays (as indicated by the exclamation marks outside the array definitions)


2.) Operations: In GraphQL, an operation can be of type:


3.) Resolvers: In a REST API, data is retrieved/mutated from multiple specific endpoints. And each endpoint has a defined structure of data that it returns/modifies which essentially means that the response is encoded in that specific url (because we know exactly what a specific url is supposed to return). This is also known as a fixed response. In GraphQL, however, a single endpoint is used and this is possible because the structure of the response is not fixed and the client has more flexibility to request exactly what they want from the API. For our GraphQL API to make sense of client queries, we need resolver functions to interpret our requests and return exactly what the client wants.

Sample schema of resolver functions using our initial example:

type Query {
  org_detail( id: ID!): Organization!
  all_employees( ): [Employee!]!
  employee_detail( id: ID!): Employee!
  position_detail( name: String!): Position!
}

type Mutation {
  create_emp(id:ID!, name:String!, position:[Position!] ): Employee!
}

type Subscription {
  listen_for_new_employees(….): [Employee!]
}

In our query operation, org_detail for instance, accepts an id which is required and returns a value of type Organization (which is also required).


How to write GraphQL requests/queries

Sample query:

query {
  org_detail( id: yadayada) {
    name
  }
}

Sample response:

{
  “data”: {
    “org_detail”: {
      “name”: “io-hub.software”
    }
  }
}

Now a a slightly more complex query:

query {
  all_employees( ) {
    name
    // don’t care about the duration
    position {
      name
      //don’t care about responsibilities
      Managing {
        name //will return list of people managed by this employee
	// don’t care about everything else
      }
    }
  }
}

Response:

{
  “data”: {
    “all_employees”: [
    {
      “name”: “Albus Dumbledore”,
      “position”: [
      {
        “name”: “Headmaster”,
        “managing”: [
        {
          “name”: “Hermione Granger”
        },
        {
          “name”: “Harry Potter”
        }
      }]
   }]
  }
}

Do you see the pattern? GraphQL enables us to request only what we want from the server and nothing else, all through a single endpoint.

Advantages of GraphQL

1.) GraphQL enables us to use a single endpoint instead of multiple endpoints. In RESTful APIs, it becomes increasing more difficult to keep track of multiple endpoints as your API grows. This can eventually result in multiple endpoints that are very similar or that essentially do the same thing.

2.) No over-fetching or under-fetching:

By allowing clients to request exactly what they want and nothing else, GraphQL ensures that no unnecessary data is returned (over-fetching). The opposite of over-fetching is under-fetching and this occurs when an endpoint doesn’t return enough data which leads to making multiple requests to multiple endpoints (or creating extra endpoints to satisfy the request) as can happen with some REST APIs.

3.) As an extension of the advantage above, GraphQL enables efficient data loading by keeping the amount of data transferred over the network to a minimum.

4.) Encourages rapid development. With just the schema definition, development on both the client-side and server-side can go on simultaneously since the schema tells us just about everything we need to know about the API.

Disadvantages of GraphQL

1.) Complex nested queries: Since one of the advantages of GraphQL is query nesting through a single endpoint, if a client requests too many nested fields at once, this can reasonably slow down the API. To solve this, there can be a query limit depth on the server-side (or client-side) to avoid excessive query nesting by the client.

2.) Handling complex queries as a server-side developer: To satisfy the standards that make GraphQL more efficient than RESTful APIs, complex queries have to be made most times to the database. If you’re using a relational database like SQL, handling such complex queries with JOINs and so on becomes increasingly more difficult and you’ll need all the tricks and tools in the bag (including harry potter’s wand) to ensure your database queries are as efficient as possible. If not, this will also reasonably slow down the API.

3.) To cache or not to cache:

Caching is much more difficult to implement in GraphQL when compared to a RESTful API. In a REST API, since each resource is usually associated with a url, the url can be used as an identifier for the resource which makes caching the request result much easier. However, in a GraphQL API, since a single endpoint is used and clients can pick and choose what they want, it becomes increasingly more difficult to anticipate what to cache and what not to.

In conclusion, as you decide whether the GraphQL architecture is the right choice for your API, just bear in mind that this is a relatively new technology and will be improved further as its adoption grows even more. Thank you for reading this post. If you enjoyed this, please check out our other blog posts.


Resource(s)

https://graphql.org