One of my side projects involves writing a around the Universal Chess Interface ( ). I originally developed a mock implementation and . That used version one of Apollo’s client/server stack, which . One of the biggest changes was the subscriptions interface and implementation, and I struggled for many hours to get that to work. Part of the problem is that the documentation is not very complete and rather scattered. This post will cover the most basic implementation of subscription service and the client code that uses it. GraphQL API UCI wrote about it awhile back changed quite a bit in version two Getting started The GraphQL server will be based on , which in this case will use an Express server as middleware. Subscriptions will use a that is attached to a plain HTTP server (also managed by ApolloServer, as we shall see). ApolloServer WebSocket There are two clients: the , and a client for use by Mocha to test the API outside of a GUI. For simplicity, I’ll keep the Mocha client code in the same folder as the server code. I also use Babel so I don’t have to think about and the like. GraphQL Playground Michael Jackson Scripts With that in mind, here are the packages to be installed: apollo-link, apollo-link-http, apollo-link-ws, apollo-server-express babel-cli, babel-core, babel-preset-env graphql, graphql-tools subscriptions-transport-ws mocha, chai I’ll provide a link to a working code repository at the end of this article. The Server The server is as basic as I could make it: express ; { ApolloServer } ; http ; { typeDefs } ; resolvers ; PORT = ; app = express(); server = ApolloServer({ typeDefs, resolvers, }); server.applyMiddleware({ app }); httpServer = http.createServer(app); server.installSubscriptionHandlers(httpServer); httpServer.listen({ : PORT }, () => { .log( ); .log( ); }); import from 'express' import from 'apollo-server-express' import from 'http' import from './schema' import from './resolvers' const 3031 const const new const port console `🚀 Server ready at http://localhost: ` ${PORT} ${server.graphqlPath} console `🚀 Subscriptions ready at ws://localhost: ` ${PORT} ${server.subscriptionsPath} An ApolloServer is created with schema and resolver parameters. The call passes in an express application instance. Finally, an HTTP server is created to handle the web socket interface to the subscription service. Both GraphQL and the subscription websocket share the same port, but under different protocols. applyMiddleware The Schema { makeExecutableSchema } ; resolvers ; typeDefs = [ , ]; options = { typeDefs, resolvers, }; executableSchema = makeExecutableSchema(options); executableSchema; { typeDefs }; import from 'graphql-tools' import from './resolvers' const ` type Query { go: String! } type Subscription { info: String! } ` const const export default export The schema is very basic: will return a string acknowledgment, but behind the scenes it will fire off a method that sends publish notifications to subscribers. Subscribers subscribe through the subscription API. go info We can see how this works in resolvers.js: { PubSub } ; pubsub = PubSub(); TOPIC = ; infos = [ , , , ] publish = { setTimeout( infos.forEach( pubsub.publish(TOPIC, {info})), ) } { : { : { publish(); } }, : { : { : pubsub.asyncIterator([TOPIC]), }, }, }; import from 'apollo-server-express' const new const 'infoTopic' const 'info1' 'info2' 'info3' 'done' const => () => () => info 1000 export default Query go => () return 'going' Subscription info subscribe => () I’ve made the resolvers deliberately simple. For example, the asyncIterator method from PubSub is quite sophisticated (it supports filters and authentication, for example). Since it is already , I won’t delve into various options here. All the resolver above does is to publish an to all subscribers, passing objects as the body of the subscription. well-documented infoTopic info The Client As I mentioned, I’ll use two clients for testing. One is the built-in Prisma Playground, a service automatically provided by the ApolloServer (FYI: ). you can turn this feature off in production Testing in Playground To test, I’ll open Playground in Chrome, at Within Playground you can open up multiple tabs. For the first, I’ll subscribe to the : http://localhost:3031/graphql. infoTopic When this command is played, you will see a ‘Listening …’ response in the right pane, as shown above. Now you’re subscribed. Open another tab within Playground and query go: This sends back a response of “going”, so everything is okay. Now, going back to the subscription tab, you will see the published output: Testing using Mocha/Chai There’s a lot of boilerplate in setting up a client, so I’ve created a utility file to handle query and subscribe operations. It’s called fetch.js: fetch ; { execute, makePromise } ; { WebSocketLink } ; { SubscriptionClient } ; ws ; { HttpLink } ; gql ; uri = ; wsUri = ; link = HttpLink({ uri, fetch }); wsClient = SubscriptionClient(wsUri, { : }, ws); wsLink = WebSocketLink(wsClient); doQuery = { operation = { : gql , }; .log( ) makePromise(execute(link, operation)); }; subscribe = { operation = { : gql , }; execute(wsLink, operation).subscribe(handlers); }; doQuery; { subscribe }; /* eslint-env mocha */ /* eslint-disable import/no-extraneous-dependencies */ // see https://www.apollographql.com/docs/link/index.html#standalone import from 'node-fetch' import from 'apollo-link' import from 'apollo-link-ws' import from 'subscriptions-transport-ws' import from 'ws' import from 'apollo-link-http' import from 'graphql-tag' const `http://localhost:3031/graphql` const `ws://localhost:3031/graphql` const new const new reconnect true const new const ( ) => query const query ` ` ${query} console `$query is ` ${query} return const ( ) => query, handlers const query ` ` ${query} return export default export The fetch.js code pulls in a lot of interdependent modules. For the test operations, I use to handle the interface between the server (which has to be running, btw 😉) and the GraphQL operations used by the tests. There are actually two interfaces here: one to handle query and mutation requests vis HTTP, and another that goes through a web socket to subscribe to a topic. apollo-link Most of this comes from the , but you will have to install a few additional modules I neglected to mention earlier: documentation node-fetch (installed globally via ) npm -g ws gql The module implements the HTTP that’s becoming a standard. The module is a WebSocket implementation for Node (there are others), and is a template literal tag that you can read more about . node-fetch Fetch API ws gql here The test itself is pretty straightforward: we first , then : subscribe go chai ; fetch, { subscribe } ; chai.should(); describe( , { .timeout( ); handlers = { : { .log( , data); (data.data.info === ) { .log( ) process.exit( ); } }, : .error( ), }; it( , () => { query = ; subscribe(query, handlers); }); it( , (done) => { query = ; { res = ( fetch(query)).data; res.should.have.property( ) res.go.should.equal( ) } (e) { .error(e) done(e) } }) }) /* eslint-env mocha */ import from 'chai' import from './fetch' 'subscribe, then go' ( ) function this 5000 const next ( ) => data console `received data:` if 'done' console 'exiting...' 0 error => error console `received error ` ${error} // get the subscriber ready... 'subscribe' async const `subscription { info }` 'go' async const `query { go }` try const await 'go' 'going' catch console The object (passed to the method) is what receives the publish notifications. When the last published message is received, the test process is terminated. hander subscribe Conclusion You should explore the links provided, as there is a lot more about GraphQL subscriptions that I wasn’t able to cover in this article. I’ve also included a few relevant links, below. A complete github repository containing the code above can be found . Enjoy! here Tutorial: GraphQL Subscriptions (server-side) — Apollo GraphQL apollographql/graphql-subscriptions: A small module that implements GraphQL subscriptions for Node.js SSL on Apollo Server 2.0 + Subscriptions · Issue #1338 · apollographql/apollo-server apollo-link-ws | Apollo Link Composable networking for GraphQL | Apollo Link Apollo Client | Apollo Client