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 IAM, Amazon Cognito identity pools, 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. For more information, see Security.

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

The following example shows how to work with GraphQL subscriptions. 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 as follows:

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. To do this, 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 }), the content, version, and url won't be published to subscribers. Instead the id, author, and title would be published.

In the previous example, the subscriptions didn't have arguments. Suppose your schema looks like the following:

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

In this case, your client defines a subscription as follows:

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

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 because subtle changes enable you to modify how and when clients are notified about mutations that have occurred. To do this, see the sample schema from the Quickstart section, which creates "Events" and "Comments". For this sample schema, the following mutation occurs:

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 enable 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 get comments for all events. Additionally, if you want clients to explicitly subscribe to all comments for all events, you should remove the argument as follows:

subscribeToEventComments(): Comment

Use these for comments on one or more events. If you want to know about all events that are created, you could do the following:

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, you could do the following:

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

As a result, the client application can now do the following:

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