⚡️ Pro Feature ⚡️ This feature is bundled with GraphQL-Pro.

Overview

@defer is a directive for streaming GraphQL responses from the server to the client.

By streaming the response, the server can send the most critical (or most available) data first, following up with secondary data shortly afterward.

@defer was first described by Lee Byron at React Europe 2015 and got experimental support in Apollo in 2018.

@defer requires the new interpreter runtime which ships with GraphQL-Ruby 1.9+.

Example

GraphQL queries can be large and complex, requiring lots of computation or dependencies on slow external services.

In this example, the local server maintains an index of items (“decks”), but the item data (“cards”) is actually hosted on a remote server. So, GraphQL queries must make remote calls in order to serve that data.

Without @defer, the whole query is blocked until the last field is done resolving:

    <a href="https://user-images.githubusercontent.com/2231765/53442028-4a122b00-39d6-11e9-8e33-b91791bf3b98.gif" target="_blank" class="img-link">
      <img src="https://user-images.githubusercontent.com/2231765/53442028-4a122b00-39d6-11e9-8e33-b91791bf3b98.gif" title="Rails without defer" alt="Rails without defer" />
    </a>

But, we can add @defer to slow fields:

  deck {
    slots {
      quantity
-     card
+     card @defer {
        name
        price
      }
    }
  }

Then, the response will stream to the client bit by bit, so the page can load progressively:

    <a href="https://user-images.githubusercontent.com/2231765/53442027-4a122b00-39d6-11e9-8d7b-feb7a4f7962a.gif" target="_blank" class="img-link">
      <img src="https://user-images.githubusercontent.com/2231765/53442027-4a122b00-39d6-11e9-8d7b-feb7a4f7962a.gif" title="Rails with defer" alt="Rails with defer" />
    </a>

This way, clients get a snappy feel from the app even while data is still loading.

View the full demo at https://github.com/rmosolgo/graphql_defer_example.

Considerations

Next Steps

  <a href="/defer/setup">Set up your server</a> to support `@defer` or read about       <a href="/defer/usage">client usage</a> of it.