Hi, I'm Daisy

Here is a place for my random musings!

GraphQL EU Conference 2018

I had the wonderful opportunity to attend the GraphQL EU Conference in Berlin this summer, which is the second conference surrounding GraphQL. There were apparently double the amount of attendees this year compared to last year! There were a ton of interesting and exciting talks surrounding its current usage, and best practices and wisdom from companies who are already adopting GraphQL. I particularly enjoyed the talk “Revenge of the Monolith” by Nick Schrock, where he goes through the history of GraphQL at Facebook and how it came to be open-source and dispelled a bit of the hype over microservices.

GraphQL is a really exciting technology and one that I also spent time digging a bit deeper into. This post will go over how to replace rest APIs with GraphQL!

As you may already know, the current dominant architecture style for client-server interaction is REST (Representational State Transfer) and when people talk about APIs, they generally refer to REST APIs. If you have thought about obtaining data from another resource on the Internet with your application, you have probably come across this term or written an app that consumes REST APIs.

REST dictates a set of guidelines that should be followed during API creation. For example, in order to request or update resources, different URLs are used. All calls should be stateless, and are typically transferred through a client-server protocol such as HTTP. Objects on the server are treated as resources that can be created or deleted.

As ubiquitous as REST APIs are, they are not without problems. First, there is the problem with latency. Since interactions are with a single entity type per HTTP request, this necessitates multiple round-trips between the client and the server in order to traverse the object. You have to go through each URL and make a request for each. Second, there is the problem with inconsistency. There is no standard way to build REST APIs and with this flexibility comes a downside. Oftentimes, the designated endpoints become arbitrary code that takes in parameters accessed via HTTP requests and spits back out any data. This can lead to inconsistent code bases. Third, there is little transparency. REST APIs often become a black box of sorts from the client-side’s standpoint. Documentation is often key to understanding how to leverage and understand the API.

Furthermore, the APIs can become difficult to manage at scale when endpoints start to grow rapidly and every resource becomes designated by a different URL. Lastly, there is no built-in data validation and every API is responsible for validating and cleaning the data.

Although REST may be the norm, there are other alternatives emerging such as GraphQL.

What is GraphQL?

GraphQL is a hierarchical and strongly typed data query language for APIs that is starting to gain popularity and has seen a lot of adoption from big companies like Facebook, GitHub, Yelp, Pinterest, Shopify due to its many benefits over REST APIs. It was developed internally at Facebook in 2012 and became open-source in 2015.

As Facebook was expanding, it encountered a lot of scaling problems as more and more microservices were created for so many different things and the problem of how to fetch data consistently from all these data sources arose. GraphQL was created to combine all the different data sources into a single API.

GraphQL is comprised of a query language and a framework that processes those queries. It is language agnostic and can be implemented in any environment. It offers a lot of benefits over traditional REST APIs. Importantly, GraphQL alleviates the problem of over-fetching and under-fetching data by allowing the client to declare exactly what data is necessary. The server will return exactly that and nothing more. It is a declarative and strongly typed system that returns predictable results. The client specifies the structure of the data desired in the query and the response is returned by the server in the same structure.

In addition, it solves classic performance problems by avoiding multiple calls to the server. GraphQL enables the client to issue just a single request to the GraphQL server while declaring the use of multiple resources in potentially complex nested hierarchical data. The server understands how to handle relationships and unify all the different endpoints by federating all the requests (made by that one query) to the different REST resources that have been previously defined and deciding what is actually necessary to return. The work of processing and filtering has been offloaded to the server.

With all of the advantages of GraphQL, it should be noted that GraphQL is just a query language specification that can be implemented with a variety of languages and so setting up a GraphQL server can be a challenging task. That is why there have been a few GraphQL-as-a-service platforms created such as Graphcool and Scaphold.

Moreover, since queries are no longer idempotent, GraphQL results can’t make good use of HTTP caching like REST API results. The solution would be client-side caching, which can be achieved with tools like Relay and Apollo. Queries could be minimized with all the data on the client side.

There are some security concerns to be mindful of against malicious queries that target the deeply nested nature of queries. This can be mitigated with timeouts, query depth limits, and query complexity limits (i.e. defining a maximum complexity that can be queried).

Transitioning to GraphQL

The GraphQL approach to creating APIs is quite different from the way of developing REST APIs. First and foremost, you will need to choose a GraphQL implementation for the server component. There are many to choose from in the most popular programming languages: http://graphql.org/code. Then you will need to select a client component, which accepts queries from the frontend and connects to the GraphQL endpoint to make the request. The most popular options right now are Relay (from Facebook) and Apollo.

The key components to a GraphQL API are the schema (for your type definitions), resolvers, and queries.

Schemas

Unlike REST APIs, GraphQL relies on a schema that it queries when a request is made. The schema describes the data types of the API and defines what can be queried. A great thing about GraphQL’s approach is that as soon as a schema is created, so is the documentation. So you first have to generate a schema, which always begins with a root query.

A simple example:

type RootQuery {
    post: Entry
}

type Entry {
    title: String
    content: String
}

Here the post field returns an Entry object and the Entry object consists of a title of type String and content also of type String. In a REST API, the list of endpoints would be similar to the fields on the query types in GraphQL since they are both the gateway into getting the resource.

A vital aspect of every field is a resolver, which dictates how to fetch the actual data.

For example:

Query: {
    post(root, args) {
        return Posts.find({ id: args.id }); // the resolver
    }
}

Data can be fetched from anywhere, which enables GraphQL to act as a facade for your database, your cache, your services. A query language is essentially being built on top of your existing application code, which makes the transition so much smoother.

After you have finished creating your schema, the GraphQL server will expose your API via an endpoint. Only one endpoint is needed.

Querying Data

A GraphQL query consists of an endpoint, a query declaration, and some fields (properties that define the shape of the response we get back).

Here a new query is being declared asking for a field called post:

query {
    post{
        title
        content
    }
}

The potential JSON response (which is in the same shape as the query):

{
    “data”: {
    “post”: {
        “title”: “First Post”,
        “content”: “Here is some content”
        }
    }
}

A query can also accept arguments:

query {
    post(id: 1) {
        title
        content
    }
}

Modifying Data

Mutation is a reserved keyword in GraphQL for making modifications to your data. It is very similar to a query declaration, except that it makes changes to existing data.

A simple example that is supposed to allow you to create a new post:

mutation {
    createPost(title: ‘New Post’, content: ‘New Content’) {
	title
        content
    }
}

Other features

There are still a lot of important and interesting elements of GraphQL that are not covered in this post, such as object identification, hypermedia, caching, directives, alias, fragments, arguments, nested fields (edges, nodes). The official documentation is an excellent resource.

Conclusion

GraphQL is a very enticing project that provides a new way for clients and servers to interact in order to exchange data. GraphQL and REST APIs both have the same goals but GraphQL has made a few core changes that alters the way APIs are built and consumed and aims to improve on the ideas from REST architecture. Although it has many benefits over REST APIs, it will not serve everyone’s needs and purposes. REST is currently still the predominant architecture to follow when building APIs and it has the simplicity and integrations that GraphQL has yet to match. But there is a good chance that this will change in the near future.