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

Notify subscription pattern

Try it yourself

You can find code example for this chapter here.

In the previous chapters we've seen how subscriptions work, where the fields available for them are defined, and how to implement event filtering. Now you probably have the impression that it's relatively easy to implement real-time notifications that push data to clients whenever they need and keep them up-to-date with all changes. This is also the point where the AWS documentation and most tutorials stop.

Unfortunately, subscriptions implemented like this are hardly usable for any realistic scenario as they miss a lot of practical requirements.

First, filtering can be done only on top-level fields of the return type. In the previous examples, we used filters on the Todo items, but that's usually not what you want. When a user logs in to the app, it is interested in the new Todo items that is assigned to them. For this, we would need to move from the Todo to the User and filter by the field. And that is not possible with AppSync.

Second, subscriptions don't handle the scenario when a change needs to send multiple notifications. In a ticketing system, moving a ticket between projects needs to send 2 events: one for the deletion from the original project and a second one for a creation in the new project, otherwise there will be some information disclosure. Or when a user is deleted, its tickets should become unassigned, and that can generate several events.

And third, the subscription event contains only the fields defined by the mutation, which is usually client-controlled. This can easily break real-time functionality for a seemingly unrelated change.

To solve all these problems, we need to think about subscriptions a bit differently and break the mutation -> subscription tie. In this chapter, we'll discuss a pattern that makes subscriptions practically useful.


First, add a dedicated mutation and event for the subscription:

type TodoEvent {
  userId: ID!
  groupId: ID!
  todoId: ID!
  severity: Severity!
  todo: Todo!

type Mutation {
  notifyTodo(userId: ID!, groupId: ID!, severity: Severity!, id: ID!): TodoEvent!

type Subscription {
  todo(userId: ID, groupId: ID, severity: Severity): TodoEvent
  @aws_subscribe(mutations: ["notifyTodo"])

The TodoEvent type has all the fields on the top level that are needed for filtering. In our case, that will be the todoId, severity, the userId, and a second level of indirection, groupId. This means the clients can subscribe to updates to individual Todo items, items belonging to a user, and items under a group.

The TodoEvent type allows filtering for users and groups too

Then the notifyTodo mutation has all the same arguments as the fields of the TodoEvent. This is to make sure all these filters can be used even when a Todo item is removed. For example, without getting the userId as an argument, the resolver for the notifyTodo wouldn't know which user the deleted Todo item belonged to.

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