June 23, 2016

New features in GraphQL: Batch, defer, stream, live, and subscribe

Sashko Stubailo

Sashko Stubailo

This year, I was fortunate enough to be able to attend React Europe in Paris. This is one of the most exciting conferences in the React ecosystem, and has a special significance for GraphQL — in fact, it was at React Europe last year that GraphQL and Relay were announced as open source projects. What a year it’s been!

There were some great talks about GraphQL at the conference, and I think anyone excited about GraphQL should check them out on the React Europe YouTube channel. So that you don’t have to watch all of them, I’m going to go through my favorites and summarize them in blog post form, starting with a talk by Lee and Laney about ideas for the future of the GraphQL spec and transport.

Update in February 2017 — one of the features mentioned in this post, GraphQL subscriptions, is now an official RFC for the specification! Read about that in our newer post, “The Next Step for Realtime Data in GraphQL”.

GraphQL Future by Laney Kuenzel & Lee Byron

Watch the talk on YouTube

This talk was about some new features in the GraphQL spec based on what Facebook has been experimenting with internally. It’s a must-watch for anyone excited about the potential of GraphQL.

First, Lee Byron did a recap of how much cool stuff has been built in the GraphQL ecosystem since the spec was released a year ago. There have been lots of server implementations in different languages:

And, since Relay was released a year ago, several new GraphQL clients have popped up with different tradeoffs between complexity and features:

Next came the most exciting part of the talk for me. After emphasizing that Facebook only open sources what they use, and that these are just experiments, Lee dropped some knowledge about future improvements to the GraphQL spec and transport that address some common questions and concerns people have with GraphQL today.

1. Batch operations

This is something Facebook has been using internally for a while — the ability to send as many GraphQL queries as you want in one request, and declare dependencies between the two.

2. Defer

This is a proposal for a new directive called defer, which is intended to minimize the time to first data. When you have a large GraphQL query for your UI, you might currently need to wait for the whole result to be generated by the server and sent over the wire to see any of it on the screen. But with defer, you can specify that some part of the query can arrive later. Let’s say you do a query for the news feed, but you don’t need to get the comments right away, so you add the defer directive to the comments field. When you call the query, you first get the initial response:

That allows you to render the news feed without comments immediately, and then the server sends a second response afterwards:

This lets the client fill in the comments for that particular news feed item. Over time, the comments for all of the news feed items stream in, but even if it takes a long time to get all of them, it doesn’t block your initial render.

3. Stream

The above is already a great improvement for time to first data, but sometimes you might have some long lists that you don’t need to display all at once. Just like defer lets you delay loading fields on your result, stream lets you defer loading individual items of an array. So let’s say you want to get the news feed one item at a time; you would first get an empty array:

Then you would get each news feed item individually:

And if you have deferred fields, those come in separately as well:

Essentially, with the defer and stream directives, and a new format for sending result patches, we can solve the problem where an entire GraphQL result needs to be generated before any response is sent.

But what more can we do if we have already designed a partial result format?

4. Live

It turns out that if the server can send patches to the result, it can also patch parts of the result that have already been sent, resulting in real-time updates to the data on the client. The idea Lee showed was a live directive, which would notify the server about the desire to receive live updates about a certain field.

Let’s look at an example query with live. You would get the whole response back at first:

And then the server would send a patch updating one of the previously sent values:

This is very exciting, because it shows how much more you can accomplish with GraphQL once you have the ability to send and receive patches on the data. Notably, the design doesn’t come with any ideas about how to implement such a backend, but now that there are some sketches about what the transport could look like, people can experiment with various client and server implementations.

Reactivity today: Subscriptions

While the ideas Lee talked about are just sketches for now, there’s a mechanism used today at Facebook for delivering reactive updates: GraphQL subscriptions. Since Facebook doesn’t have a fully-reactive backend, but they do have a pub/sub system, GraphQL subscriptions are a way to get pub/sub data with GraphQL queries. The architecture at Facebook looks like this:

The syntax looks like the slide below, which is very similar to a mutation result. In fact, you can think of a subscription as the result of a mutation someone else did:

Subscriptions are a great way of taking advantage of GraphQL’s data selection and self-documenting features when subscribing to events.

While GraphQL subscriptions are not yet implemented in Relay or most open source GraphQL servers today, they are used heavily by Facebook to power live comments, and can serve as a great template for how to implement such an architecture in your server.

Editorial — My thoughts on the talk

It shows GraphQL is developing in exciting directions: These are some very welcome and exciting additions to GraphQL. In particular, one of the biggest criticisms of GraphQL is that you have to wait for the whole response to be generated before getting any data, a concern which these proposals address head-on. I also love that these developments demonstrate there is much more in store for the future of GraphQL, and more exciting ways that it can bring value to application developers beyond what their current tools offer.

There’s a great idea for a new transport format: The most important part here is the introduction of a new way to send GraphQL data with patches that indicate the path in the result where they should be applied. Because most smart GraphQL clients, like Relay and Apollo Client, are designed with a normalized cache that stores objects and fields, the data delivered by streaming results and subscriptions is very easy to integrate into the cache. And you can imagine many other ways to use such a streaming format of data delivery beyond what was proposed in the talk — for example, a server that automatically retries resolvers that result in errors, and then patches the response with the correct result, all without blocking the UI from rendering.

There is cool stuff to experiment with: I’m really excited to experiment with these features in Apollo. Since Apollo includes client and server implementations, we can easily test out experimental transport features. One thing that’s coming up very soon in Apollo is first-class batching support. We recently added a feature to Apollo Client that merges queries into one request, and we’re working on implementing batching on the server to avoid rewriting queries on the client and to support dependencies between queries.

It foreshadows great additions to the specification: So why do these things need to be in the spec at all? While it’s possible to do some hacks in the current GraphQL ecosystem to achieve the features above (for example implementing defer by sending multiple requests, or live by polling parts of a query), I think having it in the spec will be a huge benefit. One of the biggest benefits of GraphQL is the wealth of different implementations on top of many different languages and frameworks. The idea that any GraphQL server can work with any client is huge, and gives developers a ton of flexibility, just like with REST. For GraphQL to become a widespread standard, I think this compatibility is crucial. It would be sad to end up with a huge wealth of custom extensions on top of the spec, making different clients and servers unable to work together.

It talks about other ways Facebook is using GraphQL that aren’t yet available in open source: GraphQL subscriptions look like a great way to push data to the client in response to events, and can be a great idea when you already have a message channel set up to send events like chat messages, notifications, and the like. You get the simplicity of a pub/sub system, but with the querying and filtering capabilities of GraphQL.

I’m very curious to hear other people’s thoughts on these developments! Drop me a line in a response here on Medium or on Twitter, and let’s talk.

Follow us on Medium to get more GraphQL news and articles. Also, check out the next talk summary, Dan Schafer’s GraphQL at Facebook!

Written by

Sashko Stubailo

Sashko Stubailo

Read more by Sashko Stubailo