Skip to content

What is GraphQL

GraphQL is an alternative to REST for fetching data from a server. Traditionally, the de-facto interface for fetching data from a server to a client is using RESTful APIs to fetch data. However there are a few challenges with using RESTful APIs including uncertain type safety, overfetching or underfetching, out-of-sync documentation, rapid product development cycle, etc. There are ways to address each of these concerns but all that requires extra work and have to be built by the developers. However GraphQL solves these issues natively without extra work required.

GraphQL (short for Graph Query Language) is a declarative query language for gatting and updating data from your APIs. It was developed and opensourced by Facebook in 2015 (although it was already in use internally for several years before that).

It allows you declare the data that you want to receive and the GraphQL API returns exactly that, nothing more (goodbye overfetching!). This also works for complex nested data structures, which would typically require multiple roundtrips to fetch all the data. This helps you create network performant applications since you no longer have to fetch bloated data sets when you only need a subset of the data.

Also it makes use of a single endpoint for all requests and request types, instead of multiple endpoints that return only a predefined set of data.

GraphQL is also strongly-typed. All the data types and structures expected to be returned from the GraphQL API have to be designed and defined as a schema which would be used to validate requests that are received by the GraphQL API. This guarantees that the server only receives the data type it expects.

One other really cool feature is that GraphQL allows introspection of the schema such that clients and tools can know exactly what data types an API needs. This helps with developing awesome GraphQL developer tools like Altair and allows clients validate their queries before sending them to the API.

An example

Now that we know what GraphQL is, what does it actually look like? Assuming we have an API for a blog at api.blog.io. In this API we have a couple entities as defined below (using typescript annotation):

ts
interface Post {
  id: number;
  title: string;
  content: string;
  imageIds: number[];
  authorId: number;
  categoryId: number;
}

interface Category {
  id: number;
  title: string;
}

interface Author {
  id: number;
  name: string;
  postIds: number[];
}

interface Image {
  id: number;
  postId: number;
  name: string;
  url: string;
}

In a traditional REST setup, this will consist of at least the following endpoints:

  • Post - api.blog.io/posts
  • Category - api.blog.io/categories
  • Author - api.blog.io/authors
  • Image - api.blog.io/posts/{id}/images

Now let's consider different scenarios:

Scenario 1 - Get name and ID of all posts

We can achieve this in REST by making a GET request to api.blog.io/posts. This will return all the posts. (1 query in total)

TIP

The REST API could be improved to accept an include query parameter which will allow you to specify the exact fields you want to receive, like api.blog.io/posts?include=id,title. However this gets a lot more complicated the more complex and nested your data is.

We can achieve this in GraphQL using the following query:

graphql
{
  posts {
    id
    title
  }
}

This returns a list of objects containing id and title for all the posts.

As you can see, we are able to fetch exactly the data we want instead of fetching the whole thing. Also the query syntax is concise and easy to read.

Scenario 2 - Get all the posts of an author

We can achieve this in REST by making a GET request to api.blog.io/authors/{id}. This gives us the author object. Then we either query each of the posts in author.postIds one after the other using api.blog.io/posts/{id}, or we fetch all posts again and filter by the post IDs list for the author. (2 queries in total)

TIP

The REST API could be improved by implementing filtering functionality on it such that you can pass a list of IDs to api.blog.io/posts and it returns the filtered list.

We can achieve this in GraphQL using the following query:

graphql
query authorPosts($authorId: Int!){
  author(id: $authorId) {
    posts
  }
}

This query is a little more complicated because we are using GraphQL variables for the authorId instead of setting it directly like author(id: 1). Using GraphQL variables make it much easier to reuse GraphQL queries.

Scenario 3 - Get a list of names of the authors and URLs of the images of all posts in a category

We can achieve this in REST by making a GET request to api.blog.io/categories/{id}/posts. This gives us the list of posts for that category. Then we make a GET request to api.blog.io/authors/{authorId} with the authorId for each post, which gives us a list of authors. Then we make a GET request to api.blog.io/posts/{postId}/images for each post, which gives us a list of image lists. (2n + 1 queries)

We can achieve this in GraphQL using the following query:

graphql
query categoryAuthorsAndImages($categoryId: Int!){
  category(id: $categoryId) {
    posts {
      author {
        name
      }
      images {
        url
      }
    }
  }
}

With just a single query, we can fetch complicated nested data from our API, and yet it is easy to understand what we are doing from the query!

TIP

So far we have looked at sending query requests for fetching data. However GraphQL also support the mutation (for updating/mutating data) and subscription (for subscribing to realtime changes) request types. Learn more about them here.

GraphQL Schema

As mentioned above, GraphQL is strongly typed and requires developers of a GraphQL API to define the structure of the data that will be received and returned by the API. This defined structure is what is referred to as the GraphQL schema. The GraphQL schema needs to be implemented in the programming language of the API. However since GraphQL is language agnostic, it has its own language for defining the GraphQL schema called SDL (Schema Definition Language) which has a simple yet powerful syntax.

TIP

You can download the SDL for a GraphQL API in Altair from the menu inside the docs section. You can also load a GraphQL schema directly into Altair if for example, you are offline and can't connect to the API, or the API has introspection disabled, which is required to power the docs.

The SDL for our hypothetical blog API could look like this:

graphql
type Post {
  id: Int!;
  title: String!
  content: String!
  images: [Image!]!
  author: Author!
  category: Category!
}

type Category {
  id: Int!
  title: String!
  posts: [Post!]!
}

type Author {
  id: Int!
  name: String!
  posts: [Post!]!
}

type Image {
  id: Int!
  post: Post!
  name: String!
  url: String!
}

Conclusion

GraphQL is a powerful tool and has a lot of potential. This gives you a brief introduction into what GraphQL has to offer but it definitely does not cover it all. GraphQL is still evolving everyday with the community constantly working to improve the existing standards. There are several other features in GraphQL like directives that are not covered here.

To learn more about all the features of GraphQL, take a look at the graphql docs. You can also explore the GraphQL features within Altair GraphQL client. Download it today and try it out with a public GraphQL API (e.g. Rick and Morty https://rickandmortyapi.graphcdn.app/).