GraphQL is a query language and runtime resolver for APIs, used to bring more structure to services that work with complex data. With GraphQL, clients can request only the data they need, and nothing more.

The Difference Is Who Sets the Schema

Traditional REST APIs involve an API server that responds to requests with structured data, usually in the form of JSON. If you make a GET request to api.com/users/, you might expect to get back in response something along the lines of:

Your app will look different, but the point is that the schema is defined by the REST endpoint. You only made a request to /users/, but you got back all this data.

This works well, though, if you know what data you’ll be getting back, and it’s the standard for the majority of services on the web. Though, if you’re making PUT requests, you must supply the API with the proper parameters for it to work with, or else you will run into errors. Of course, you can use URL parameters to pass in values to the API, such as the user ID to fetch, which you can use to make the API more dynamic.

GraphQL APIs do things a little differently. Rather than making individual requests to different endpoints, which all represent different pieces of data, a GraphQL application will send a request to a single origin. The request body contains a schema and tells the API what data to send back. This way, you can request complex data in only one request, and the API never sends back more than it is told to, cutting down on large response sizes.

For example, if you wanted to request the email address of a specific user, you could send a GraphQL request to the api.com endpoint, with the following query:

It doesn’t matter if the “User” object contains fields for other information; because you only requested the email, you’ll only get sent the email. Of course, you’re still getting sent a JSON object like REST, and you’re still communicating in the same fashion, but the requests are much more informative.

For apps with complex schema, this sort of API can be very useful for organizational reasons. With GraphQL, you’re forced to strictly define your schema when setting up the API, much like static typing forces you to adhere to structs and types. The structure of the data is easily referenceable and modifiable. You can easily achieve this same effect with standard REST APIs, but GraphQL enforces it.

On top of that, GraphQL queries can be more efficient. For example, a popular problem is the “friends of friends” query. In a REST API, you’d have to send a request for the user in question and then upon receiving the IDs of his friends, you send out individual requests for each friend’s info and then filter that all out for the stuff you want. Of course, you can (and should) implement a new endpoint to perform this query on the database side of things, but that’s a bandaid on the real problem.

With GraphQL, this query is simple. You only need to specify that you want the name for each friend, and (assuming the backend is configured to handle this properly) the API will handle this interaction naturally, without special configuration for each request.

Of course, GraphQL is not without its downsides. For simple apps, it’s far too complex to replace a basic REST endpoint. Also, with a traditional REST API, you get the benefit of being able to split up different routes. For example, /users and /posts can be handled by separate serverless Lambda functions, and can be worked on and updated independently from each other, a concept known as microservices backend. For GraphQL, it’s much more centralized and harder (though not impossible) to split up into separate chunks.

How Do You Get Started?

GraphQL has plenty of server libraries for different languages, but it’s commonly used with JavaScript and NodeJS.

There are two things that a GraphQL query needs—a schema, which defines the structure and types of the data, and a resolver, which takes an input and returns the value associated with the schema. In the resolver, you can do things like fetch database requests, modify data, and perform any actions you need, provided it all condenses down to a return value matching the schema at the end.

For complex apps, the schema and related resolver can be generated automatically based on the structure, but at the end of the day, the schema is just a type definition, and the resolver is just an object with functions that resolves different keys in the schema.

For more information on how to set up a full GraphQL server, you can read GraphQL’s guide on installing and using it with Express.