AWS AppSync
AWS AppSync Developer Guide

Real-Time Data

GraphQL Schema Subscription Directives

Subscriptions in AWS AppSync are invoked as a response to a mutation. This means that you can make any data source in AWS AppSync real time by specifying a GraphQL schema directive on a mutation. Subscription connection management is handled automatically by the AWS AppSync client SDK using MQTT over Websockets as the network protocol between the client and service.

Note: To control authorization at connection time to a subscription, you can leverage controls such as AWS IAM, Amazon Cognito Identity, or Amazon Cognito User Pools for field level authorization. For Fine Grained Access Controls on subscriptions, you can attach resolvers to your subscription fields and perform logic using the identity of the caller and AWS AppSync data sources. Please see Security for more information.

Subscriptions are triggered from mutations and the mutation selection set is sent to subscribers.

The following example shows how to work with GraphQL subscriptions. Notice that it doesn't specify a data source, because the data source could be AWS Lambda, Amazon DynamoDB, or Amazon Elasticsearch Service.

To get started to with subscriptions, you must add a subscription entry point to your schema:

schema { query: Query mutation: Mutation subscription: Subscription }

Suppose you have a blog post site, and you want to subscribe to new blogs and changes to existing blogs. You would add the following Subscription definition to your schema:

type Subscription { addedPost: Post updatedPost: Post deletedPost: Post }

Suppose further that you have the following mutations:

type Mutation { addPost(id: ID! author: String! title: String content: String url: String): Post! updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post! deletePost(id: ID!): Post! }

You can make these fields real time by adding an @aws_subscribe(mutations: ["mutation_field_1", "mutation_field_2"]) directive for each of the subscriptions you want to receive notifications for, as follows:

type Subscription { addedPost: Post @aws_subscribe(mutations: ["addPost"]) updatedPost: Post @aws_subscribe(mutations: ["updatePost"]) deletedPost: Post @aws_subscribe(mutations: ["deletePost"]) }

Because the @aws_subscribe(mutations: ["",..,""]) takes an array of mutation inputs, you can specify multiple mutations, which trigger a subscription. If you're subscribing from a client, your GraphQL query might look like the following:

subscription NewPostSub { addedPost { __typename version title content author url } }

Although the subscription query above is needed for client connections and tooling, the selection set that is received by subscribers is specified by the client triggering the mutation. To demonstrate this, if a mutation was made from another mobile client or a server, for example, mutation addPost(...){id author title }), then content, version and url wouldn't be published to subscribers. Instead id, author and title would be published.

In the example above, we showed subscriptions without arguments. If your schema looked like this:

type Subscription { updatedPost(id:ID! author:String): Post @aws_subscribe(mutations: ["updatePost"]) }

then your client would define a subscription:

subscription UpdatedPostSub { updatedPost(id:"XYZ", author:"ABC") { title content } }

One final thing to note: The return type of a subscription field in your schema must match the return type of the corresponding mutation field. In the previous example, this was shown as both addPost and addedPost returned as a type of Post.

To set up subscriptions on the client, see Building a Client App.

Using Subscription Arguments

An important part of using GraphQL subscriptions is understanding when and how to use arguments, as subtle changes will allow you to modify how and when clients are notified of mutations that have occured. To do this, refer to the sample schema from the Quickstart section, which creates "Events" and "Comments". For the sample schema, you will see the following mutation:

type Mutation { createEvent( name: String!, when: String!, where: String!, description: String! ): Event deleteEvent(id: ID!): Event commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment }

In the default sample, clients can subscribe to Comments when a specific eventId argument is passed through:

type Subscription { subscribeToEventComments(eventId: String!): Comment @aws_subscribe(mutations: ["commentOnEvent"]) }

However, if you want to allow clients to subscribe to a single event OR all events, you can make this argument optional by removing the exclamation point (!) from the subscription prototype:

subscribeToEventComments(eventId: String): Comment

With this change, clients that omitted this argument would get comments for all events. Additionally if you wanted clients to explicitly subscribe to all comments for all events, you would remove the argument:

subscribeToEventComments(): Comment

These are for comments on one or more events. If you just wanted to know about all events that get created, you might do something like this:

type Subscription { subscribeToNewEvents(): Event @aws_subscribe(mutations: ["createEvent"]) }

Multiple arguments can also be passed. For example, if you want to get notified of new events at a specific place and time:

type Subscription { subscribePlaceDate(where: String! when: String!): Event @aws_subscribe(mutations: ["createEvent"]) }

The client application could now do this:

subscription myplaces { subscribePlaceDate(where: "Seattle" when: "Saturday"){ id name description } }