Our GraphQL Experience

Chris Grice
Mar 26, 2018 · 9 min read
Photo by Raphael Koh on Unsplash

What is GraphQL?

A query language for APIs

GraphQL is usually positioned as an alternative to REST. Rather than multiple resources, with an endpoint for each, you query a single endpoint with a description of the data you want.

query {
products {
name
price
related { # We can descend into nested objects
name
price
}
inStockAt(storeId: 50) # We can provide inputs to fields
}
stores {
id
postcode
storeName: name # Aliasing too!
}
}
  • Fewer requests to fetch related data. As you can traverse between different nodes in your graph, you can fetch multiple related resources in a single request — great for slow connections!
  • Introspectable. It’s possible to query any GraphQL API to ask it about itself. Every compliant server has a __schema field which will allow you to retrieve information about the available fields and types. This allows for some really cool features, such as the automatic schema-browser provided as standard by many APIs.
GraphiQL provides traversable documentation for your API, powered by introspection queries.

Describe your data as a graph

As clients can request any data they want, GraphQL needs a way of communicating what fields are available, and how the client should expect to receive them. This is done by way of a type system, or schema.

Schemas are written in SDL, which was added to the GraphQL specification in 2018.

A runtime for fulfilling API queries

The first two elements of GraphQL are purely specifications, but we don’t currently have a way of querying our graph and getting any data back. This is where GraphQL.js comes in.

An example of resolvers in GraphQL.js

Our Experience

We’ve learnt a lot over the last year, around how to think and work with GraphQL successfully. Some of the lessons we’ve learnt have been technical, and we’ve definitely made some mistakes along the way. However, there are also benefits to adopting GraphQL that aren’t purely technical, and have actually changed how we work as a team.

Schema-first Development

One of the biggest changes to our working practices has been how we approach new stories. We work in an agile fashion at Sainsbury’s, breaking down features into stories, and then tasks. After a few sprints, we noticed that pretty much every story was now starting with a task to define our schema.

This is how our board looks pretty much every sprint. Notice the big SCHEMA tasks!

Decoupled Teams

Traditionally, building out API-driven applications has led to some pain points for us. We’ve often been in situations where progress on the client has been stalled due to the requirement of a new endpoint, or a change to an existing one. The tooling that GraphQL has provided us has improved this massively.

An example of how quickly you can mock out an API with graphql-faker.

Flexibility

Because clients only ask for the data they need, we’ve been able to be much more flexible in how we design and grow our API.

  • Non-breaking changes. As you only get the fields you request, adding new fields has no effect on any current clients. This means it’s quite easy to deploy a new field or type to your API, test it (possibly behind a feature flag), and be safe in the knowledge it won’t affect anyone else.
  • Fields for your specific use case. With REST, there’s a tendency to try and reuse endpoints, adding new filters and parameters to them to make them more generic and reusable. In GraphQL, the opposite is true — you can create fields which can take generic filters, but it’s much nicer to just create the field that you need, with only the filters you need, and only call it when it’s required.
  • Adapt and change with deprecations. Adding new fields is easy, but changing or removing other fields can sometimes be interesting. GraphQL makes this easier by allowing you to easily deprecate existing fields. Clients can then move over to the replacement over time, without a hard version cutoff.

Not a silver bullet

Though we’ve come to enjoy GraphQL a lot, there are definitely situations where it doesn’t make sense. It’s important to see it as a new tool to use, rather than a straight replacement for REST. You may want to think harder about using it in these cases:

  • File export and delivery. GraphQL returns JSON, and only JSON, so it doesn’t really make much sense for times when you’re generating files such as reports or exports. Luckily you can easily mix your GraphQL endpoint with REST endpoints, so you can fall back to a standard endpoint for these cases.
  • Authentication flows. Many OpenID or OAuth flows have specific requirements for clients, and require specific callbacks and endpoints to exist. Again, it’s easy enough to fall back to REST here when necessary.
  • Apps with a single client and server. GraphQL shines when multiple clients and use cases are in play. If you’re building a single application backed by an API, it might make more sense to build something more constrained. However, GraphQL will still work perfectly well in this situations — it’s absolutely a personal and team choice.
  • Server-to-server APIs. A lot of the benefit of GraphQL is tied up in the benefit it gives to frontend development — less requests, smaller payloads, etc. With server-only integrations, these benefits aren’t there. However, if you do have multiple consumers or use cases, it may still be worth investigating if GraphQL is a good fit.

Build things faster and better

Ultimately, we’re delighted with GraphQL as a technology. It’s not a silver bullet, but for our use case it’s ideal.

Sainsbury's Engineering

A dive into some of the engineering work done behind the scenes at Sainsbury's. Interested in working with us? Check out open roles at sainsburys.jobs.

Thanks to Luciano Visentin.

Chris Grice

Written by

Engineering @ Sainsbury’s

Sainsbury's Engineering

A dive into some of the engineering work done behind the scenes at Sainsbury's. Interested in working with us? Check out open roles at sainsburys.jobs.