@felixfbecker on October 25, 2017
Robert Zhu (@rbzhu is a software engineer at Facebook, working on GraphQL. Before, Robert worked at companies like Microsoft and even founded his own company. This talk explains the What, Why and How of Subscriptions, how to build your own GraphQL subscriptions server and the differences to live queries.
The talk starts with a demo of GraphiQL exploring a Game of Thrones API:
Executing this query returns a list of houses, their name, amount of banner men and signature words.
The request/response lifecycle of this operation is straight forward:
Writes in GraphQL are called "mutations" and work with the same request/response lifecycle. They also always return a value.
Given that we can mutate values, how can we build an application that displays real-time changes?
Enter GraphQL subscriptions, a third type of operation like query
and mutation
:
If the operation is a subscription, the result is an event stream called the "Response Stream" where each event in the event stream is the result of executing the operation for each new event on an underlying "Source Stream".
Executing a subscription creates a persistent function on the server that maps an underlying Source Stream to a returned Response Stream.
Imagine we had a microservice architecture like this:
The different microservices are wired together through an event bus.
Now lets imagine we get a new requirement: We want to detect when a suspicious activity occurs. So we add a new microservice: the Alarm microservice. The Alarm microservice acts as a subscriber to the other microservices. For example, whenever a login occurs, it can inspect that login event - triggering an alarm e.g. when a login fails repeatedly from an unusual location.
On the GraphQL level, the GraphQL query causes the subscription service to derive the set of domain-specific events from the GraphQL document and subscribe to the event bus for these events. This forms a "source stream". Whenever an event arrives from this "source stream", the subscription service combines it with the document and executes the resulting query. The result is sent back to the client along the "response stream".
The lifecycle after the subscription service stays very similar to the usual request/response lifecycle.
Subscriptions introduce a certain complexity to the stack:
The solution to this differ depending on the scale:
Single Process | Distributed | |
---|---|---|
Streaming Transport | WebSockets, SSE, HTTP long polling, RSocket, MQTT | (same) |
Connection Handling | In process/Middleware | Gateway/Proxy |
Source Stream | EventEmitter, .NET Events | Redis, Kafka, SQS, Pusher |
Subscription Session Data | In-memory collection, file | Database, Cache |
If you are using Facebook, you are using GraphQL subscriptions. These Facebook features are powered by GraphQL Subscriptions:
Subscriptions are part of the official GraphQL specification. There is a reference implementation in JavaScript, Relay Modern support and a lot of community support from Apollo, Graph.cool, Scaphold and more.
The difference between Subscriptions and live queries is the difference between observing state and observing events. An example for observing state is observing updates to a value that was 10 before and knowing it is now 11. An example for observing an event is observing the event of increments to the value, and knowing that the value that was 10 before was just incremented by 1.
Subscriptions | Live Queries |
---|---|
Know why data changed | Convert any existing query |
Fine control over publish | Simple fallback (polling) |
No server-side changes |
Subscriptions | Live Queries |
---|---|
Streaming support | Streaming support |
Reactive API/Language | Reactive API/Language |
Streaming/event system | Reactive data layer |
Domain-specific events |