Working with GraphQL subscriptions

API Connect for GraphQL allows you to set up GraphQL subscriptions for every data source.

In addition to queries and mutations, GraphQL also offers subscriptions as an operation type. Subscriptions allow a GraphQL API to push updates to a client in real-time rather than requiring the client to poll the server for new data.

API Connect for GraphQL watches for changes in your data source and pushes them to your GraphQL API. Subscriptions support the graphql-transport-ws subprotocol as exemplified by the npm package graphql-ws.

Implementing subscriptions

A typical implementation is GraphQL query polling, which periodically runs a GraphQL query and returns a new subscription result whenever the result of the subscription changes. You can do this with API Connect for GraphQL quickly and without additional infrastructure. You'll also have to trade off the overhead of regular polling and the possible lag in noticing a change. API Connect for GraphQL will execute queries on behalf of a subscription with a reduced cache TTL (time to live).

Polling queries

A subscription field provides a @materializer GraphQL query for polling queries. This query is resolved using the same endpoint, and if the data changes, it is returned to the subscription channel.

In the following example, we'll use a simple random number generator. The field Query.random will return a random number between 0 and 999999, generated by a JavaScript function defined in the ecmascript option of the @rest directive.

type Random {
  number: Int
}

type Query {
  random: Random
    @rest(
      endpoint: "stepzen:empty"
      ecmascript: """
      function transformREST(s) {
          return ({
            number: Math.floor(Math.random() * 999999)
          });
      }
      """
    )
}

You can add a subscription field that polls Query.random as follows:

type Subscription {
  random: Random @materializer(query: "random")
}

Test this subscription with the following CLI command:

stepzen request 'subscription { random { number}}'

The response looks like the following example:

Subscribed to ws://localhost:9000/stepzen-subscriptions/YOUR_ENDPOINT/__graphql
event #1 (+1.5s)
1 | {
1 |   "data": {
1 |     "random": {
1 |       "number": 468435
1 |     }
1 |   }
1 | }
event #2 (+9.4s)
2 | {
2 |   "data": {
2 |     "random": {
2 |       "number": 754591
2 |     }
2 |   }
2 | }

This example does not demonstrate the filtering that happens on subscriptions. Suppose our example can also return random strings. In that case, after the subscription selection is evaluated, subscription { random { number string } }, then the resulting selection is checked for differences against the prior result. If there is a difference, the new value is pushed to the client.

To obtain consistent results, the API Connect for GraphQL server might reduce caching when executing subscription queries, so your backend services might see an increase in queries.

Using subscriptions

GraphQL APIs are implemented over HTTP -- except for subscriptions, which are implemented over WebSockets. To invoke a subscription, you must use a client that supports graphql-transport-ws; for example the stepzen request command provided by the API Connect for GraphQL CLI.

You can use subscriptions with the CLI, or with a JavaScript client as explained in the sections that follow.

Using subscriptions with the CLI

With the API Connect for GraphQL CLI, you can use the stepzen request command to execute a subscription. The stepzen request command opens a WebSocket connection to the API Connect for GraphQL server, executes the subscription, and then displays the results of the subscription as they are received.

To use the stepzen request command, you'll need a API Connect for GraphQL workspace in the current directory. You can then use the stepzen request command to execute a subscription. For example, to execute the subscription subscription { random { number}}, run the following command:

stepzen request 'subscription { random { number}}'

See API Connect for GraphQL CLI for more information about the stepzen request command.

Using subscriptions with the JavaScript client

You can also use subscriptions directly from a JavaScript application, preferably using the library graphql-ws. This library uses a sub- protocol of WebSockets known as graphql-transport-ws (not to be confused with the deprecated library graphql-transport-ws from Apollo).

Authorization information (like your API Connect for GraphQL API key) is specified in graphql-ws as connectionParams.

You can find a complete example of using API Connect for GraphQL subscriptions with graphql-ws in the examples.

Subscriptions and URIs

The URIs for subscriptions include a wss code for secure WebSockets prefix (or ws for local docker), and prefix the path with stepzen-subscriptions as shown in Table 1.

Table 1. endpoint URLs and their corresponding subscription URIs
endpoint URL endpoint subscription URI
http://localhost:9000/YOUR_ENDPOINT/__graphql ws://localhost:9000/stepzen-subscriptions/YOUR_ENDPOINT/__graphql
https://ACCOUNT.stepzen.net/YOUR_ENDPOINT/__graphql wss://ACCOUNT.stepzen.net/stepzen-subscriptions/YOUR_ENDPOINT/__graphql

Replace YOUR_ENDPOINT with the name of your endpoint and YOUR_ENDPOINT with your API Connect for GraphQL domain. When you deploy your endpoint to API Connect for GraphQL, the subscriptions URI is displayed so you can note it down.