Bored with REST? GraphQL Introduced

GraphQL is a declarative query language created for communication with Internet services.

Is GraphQL a Replacement for REST?

Nowadays the most popular approach to build API for Internet services is REST (Representation State Transfer). GraphQL is rethinking the way of building API. GraphQL is not a replacement for REST technology but it is a different solution for problems where REST is weak. GraphQL doesn’t cover such features like file uploading, and can’t fully substitute REST approach of architecting network services.

Open Flexibility of RESTful Services

REST as architecture approach is rather a best practice than a protocol. It gives flexibility in building API because service creators are not constrained to use either a result exchange format or a strict endpoint naming convention. REST doesn’t specify the type system between a server and a service user. API developers are free to choose their own XML or JSON schema, or another serialization format. Therefore, REST client and server should control the schema on their own.

No REST Rich Parameters

Managing complex parameters in REST is not straightforward. A feasible approach uses POST HTTP request method with JSON/XML object payload. But making that for fetching break up the ideology of fetching queries via GET HTTP method. Another approach is to use nested parameters:

GET /api/v1/customers?filter=all&pagination.offset=0&pagination.limit=10

Every nested field is prepended by a parent object name with dot.

GraphQL Single Entry Point

REST encourages to use many endpoints. Every endpoint is usually related to a different entity. Operations might be a part of entity’s endpoint path or determined by different HTTP request methods.

Example of Customer entities representation:

GET /api/v1/customers - list customers
POST /api/v1/customers - create a customer
GET /api/v1/customers/c1 - get the customer with ID c1
DELETE /api/v1/customers/c1 - delete a customer record with ID c1

In complex APIs there might be plenty of these routes and query parameters are often introduced to provide additional filters or other options. It makes API not intuitive and requires the creation of good documentation.

GraphQL assumes to use one central API entry point. In some cases, additional entry points are allowed, but one entry point is quite enough for flexible GraphQL API.

POST /api/v1/graphql - one entry point for all requests

No REST Rules How to Manage Relations

How to represent addresses Entities connected to certain customer Entity? Related entities are often represented as a subpath of a parent entity’s path.

Example of representation of Customer and related Contacts entities:

GET /api/v1/customers/c1/contacts - get contacts of a customer with ID c1

GraphQL Types

As mentioned before in REST client and server interpret data are transferred via endpoint in their own way. Apart from REST, GraphQL provides Strong Type System. GraphQL provides flexibility to define its own types, and express API calls in terms of these types. GraphQL language supports primitive types, Enums, Objects, abstract types — Interfaces and Unions. Moreover, fields might be optional or required.

GraphQL Interfaces

GraphQL allows defining Interfaces. Indeed interface has the same meaning as the interface in OOP and programming languages like Java.
 Interfaces in GraphQL define the set of fields, that might be inherited by interface implementations — Objects.

For API developers it means that API calls might be general!

For example, it’s possible to define API call to search several kinds of Objects, that implement the Searchable interface:

interface Searchable {
id:String
}

The call might look like:

Query {
searchCatalog(term:String):\[Searchable!]!
}

And there might be several implementations of the Searchable interface:

type Book implements Searchable {
name:String
author:String
}

type Magazine implements Searchable {
name:String
weekly:Boolean
}

Accordingly, both Books and Magazines are searchable by searchCatalog request.

GraphQL Objects

Objects are types that consist of fields. As mentioned before, Objects might implement one or several Interfaces, but it is not required. Objects represent problem domain’s entities that API call returns. In addition, GraphQL introduces Input Objects — a special kind of objects that passed as fields arguments.

GraphQL Connections

Subqueries on a GraphQL object are often called as connections. Connections might have their own argument list. It looks like an additional call inside an object. It gives an opportunity to query fields inside objects.

query SearchForMagazine {
searchCatalog(term:"Magazine") { /// returns list of Searchable
name
}
}

UI-Centric API

GraphQL provides a proper way to build API looking from front-end point of view. It doesn’t matter what kind of client uses this API — web applications or iOS/Android apps. Services based on REST technology often provide different API depending on the client platform, that shows how hard it might be combine API with different requirements.

Example GraphQL query for whole UI view rendering:

query CertainCustomerQuery {
customer(id:"c1") {
id
name
contacts {
id
phone
}
}
}

This query might get all the necessary information for rendering UI of customer page with ID “c1”. Unlike using REST approach a client should make two different queries and collect results together — fetch customer entity separately from contact entities.

GraphQL Call Structure

GraphQL request structure is comparable to the path in a Graph that front-end client would like to receive.

Unlike Graph Database languages GraphQL is an RPC query language, but not a Graph traversing language. For instance, Neo4j’s Graph query language Cypher has a different ideology and is more similar to SQL.

Top-level objects in GraphQL are Query and Mutation. In fact, these objects are the same objects as the other in API definition. By default GraphQL server libraries (like Scala GraphQL implementation) expose only types deduced from these two top-level objects.

Connections are a special kind of fields in GraphQL type that are actually subqueries. These fields often represent related entities. On the server side, connections are described as resolvers — callback functions that implement subquery fetching.

Batch queries

Batch querying is not GraphQL specification term, but it is the way exactly how GraphQL works. GraphQL query might enclose several subqueries, which in REST architecture will be as separate calls. This feature decreases traffic between client and back-end side, reduces a call latency, and leads to a better UI response time.

Batch Security Validation

Another advantage is having less overhead for security checks. In case of many API calls a backend must validate all calls, even when they are building one logical query. Backend leveraging GraphQL verifies one complex query instead.

Conclusions

GraphQL is a valuable approach for building Internet service architecture. Properly applying GraphQL leads to speed up services development, improvement of services quality and a better acceptance of emerging new service requirements.

In addition, summarizing interesting points of GraphQL:

  • Has a schema definition (similar to Protocol buffers and Apache Thrift — but is not a serialization format
  • Strict separation fetching and mutation queries
  • Strict separation of result objects and input objects
  • Fetches only those fields, that client needs, no more and no less
  • Result structure of query corresponds exactly to query structure
  • Supports query fields renaming (aliases)
  • Execution of several queries in one call (complex query)
  • Conditional field fetching on type basis (fragments)
  • Conditional behavior using directives
  • Abstract types: interfaces and unions
  • Own cache layer on clients side
  • Seamless versioning using fields deprecation annotation