You are viewing the preview version of this book
Click here for the full version.

Real-time data with subscriptions

AppSync has support for a third operation besides Queries and Mutations: Subscriptions. Subscriptions are a way to push data from the API to the clients in a way that fits the GraphQL world.

The nicest thing about subscriptions is that it is fully managed by AppSync. You don't need to keep track of clients and implement a fanout to a potentially large number of targets as all this is managed by AWS. All you have to do is define who can listen to what and then trigger the messages. While this is no small task, as we'll see in the next chapters, this is essentially a developer's work instead of an architect's.

When a client uses a subscription, it sends GraphQL queries for various topics then AppSync sends a notification message when an event happens. Under the hood, it is a WebSocket channel with a protocol that handles multiple independent subscriptions.

Subscriptions use a WebSocket channel to push data to the clients

With a real-time channel like this, clients don't need to poll the API for new data as the backend can push any changes to them. This enables client applications to show always up-to-date data without reloading the page.

In this chapter, we'll see how to implement pushing data to clients via subscriptions and discuss the various pitfalls and best practices.

Pushing data to clients

But first, let's talk about real-time notifications in general! While it sounds simple to push something to the clients and that magically transforms the user experience to the 21st century, but this is a nuanced topic.

No matter what technology used, a notification is a response to an event. This can be anything detectable by the system, and most of the time it is something that changes the result of a query. Queries and notifications go hand-in-hand as in most systems pushing data is to make sure the clients always see what they would see if they reloaded the page. And reloading the page sends queries, so notifications can be seen as a just-in-time selective reloading.

For example, clients can fetch items from the database on page load, but when new data is added, their views will be out-of-date:

Without a push channel, clients have an out-of-date view when something changes

In this case, a notification should be sent so that the clients now that there is a new item:

With a push channel, clients are kept up-to-date

With a mechanism like this, clients can have an always up-to-date view of the backend state.

How subscriptions work

Try it yourself

You can find code example for this chapter here.

Let's consider a simple schema with Todo items:

type Todo {
  id: ID!
  name: String!
  created: AWSDateTime!

type Mutation {
  addTodo(name: String!): Todo!

Here, we have an addTodo mutation that creates a new item in the database. Then we'll have a subscription that sends notifications when that happens:

type Subscription {
  newTodo: Todo
  @aws_subscribe(mutations: ["addTodo"])

The subscription fits into the GraphQL world, it has a name, a type, optionally arguments, and supports directives.

Before we dive into the implementation, let's see how clients can use subscriptions! For this, we'll use the AppSync console in 2 tabs where one tab listens for changes while the other one sends mutations.

The subscription query on the first tab:

subscription MySubscription {
  newTodo {
Subscribing to events on the first tab

Then on the second tab, send the mutation:

mutation MyMutation {
  addTodo(name: "todo1") {
Sending a mutation on the second tab

The event is triggered on the first tab:

The event is triggered on the first tab

As a subscription uses a WebSocket channel, you can also see the same event as an incoming message:

The event comes via the WebSocket channel

There is more, but you've reached the end of this preview
Read this and all other chapters in full and get lifetime access to:
  • all future updates
  • full web-based access
  • PDF and Epub versions