The AWS AppSync Serverless GraphQL real-time reference architecture showcases different types of real-time data broadcasting using GraphQL subscriptions over WebSockets:
- Back-end broadcasting: From a serverless backend to all clients (one to many)
- Client broadcasting: Between multiple clients (many to many)
With different types of backends:
- Amazon DynamoDB (NoSQL Serverless database)
- AWS Lambda (Serverless compute logic)
- AWS AppSync Local Resolvers (Pub/Sub, data is not persisted)
The sample app is based on second screen kind of experiences where you usually have something getting broadcasted to all connected users, that in turn can interact with each other as well as see the activity of other users in real-time. We have a single movie poster and description retrieved from the TMDb popular movies API and shared with all clients for a short amount of time before it's rotated, users can vote on how they feel about the current movie as well as express their opinion in a public chat room. The most voted movies at any specific time on different categories are displayed on a leader board.
For more information refer to the article https://medium.com/open-graphql/aws-appsync-serverless-graphql-real-time-reference-architecture-19b16f5e9b93
- Create an account on TMDb and generate an API Key absolutely free for non-commercial use
- AWS Account with appropriate permissions to create the related resources
- NodeJS with NPM
- AWS CLI with output configured as JSON
(pip install awscli --upgrade --user)
- AWS Amplify CLI configured for a region where AWS AppSync and all other services in use are available
(npm install -g @aws-amplify/cli)
- AWS SAM CLI
(pip install --user aws-sam-cli)
- Create React App
(npm install -g create-react-app)
- Install JQ
- If using Windows, you'll need the Windows Subsystem for Linux (WSL)
Click the button to load the AWS Amplify Console, connect to GitHub and provide an IAM role for the build. The end to end back-end and front-end deployment should take around 10 minutes:
After the build is finished go to the AWS AppSync Console, access your newly deployed "realtime" GraphQL API and open the Queries
section. Execute the following mutation to create the data structure that will collect and store votes in the Reviews table:
mutation {
type1: createReviews(
input: { id: 1, type: "love", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type2: createReviews(
input: { id: 2, type: "like", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type3: createReviews(
input: { id: 3, type: "meh", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type4: createReviews(
input: { id: 4, type: "unknown", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type5: createReviews(
input: { id: 5, type: "hate", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
}
IMPORTANT: The button above is using a shared TMDb API Key that can be rate limited depending on the number of deployments using it at the same time, if there's a throttling issue we recommend to create your own API Key on TMDb. In that case follow the steps below:
-
The one-click deploy button above would have created a fork of this repo in your account. Edit the file
amplify.yml
and add your free for non-commercial use TMDb API Key (refer to Prerequisites) on line 13:- export TMDB_API_KEY=<YOUR TMDB API KEY HERE>
IMPORTANT: This is a public and free API for a sample application that demonstrates different real-time use cases for unauthenticated/public users. In production scenarios secure API Keys or other important service credentials with AWS Secrets Manager or AWS Parameter Store for increased security. The current approach will use Environment Variables in AWS Lambda.
- Commit the changes to your forked repository.
- The Amplify Console will kickoff another build. Wait for the build, deployment and verification steps to finish.
- Go to the AWS AppSync Console, access your newly deployed "realtime" GraphQL API and open the
Queries
section. Execute the 5 mutations as mentioned below the one-click deploy button. - Access your app from the hosted site generated by the Amplify Console from multiple browsers or devices, testing the multiple real-time subscription scenarios (https://master.xxxxxxxx.amplifyapp.com)
-
Clone this repository:
git clone https://github.com/aws-samples/appsync-refarch-realtime.git cd appsync-refarch-realtime
-
Install the required modules:
npm install
-
Init the directory as an amplify Javascript project using the React framework:
amplify init
-
Now it's time to provision your cloud resources based on the local setup and configured features, execute the following command accepting all default options:
amplify push
Wait for the provisioning to complete. Once done, a
src/aws-exports.js
file with the resources information is created. -
Execute the following command in a shell terminal and add your free for non-commercial use TMDb API Key (refer to Prerequisites):
export TMDB_API_KEY=<YOUR TMDB API KEY HERE>
IMPORTANT: This is a public and free API for a sample application that demonstrates different real-time use cases for unauthenticated/public users. In production scenarios secure API Keys or other important service credentials with AWS Secrets Manager or AWS Parameter Store for increased security. The current approach will use Environment Variables in AWS Lambda.
-
Execute the following commands in a shell terminal to set up additional environment variables as well as configure IAM authentication:
export AWS_REGION=$(jq -r '.providers.awscloudformation.Region' amplify/#current-cloud-backend/amplify-meta.json) export GRAPHQL_API_ID=$(jq -r '.api[(.api | keys)[0]].output.GraphQLAPIIdOutput' ./amplify/#current-cloud-backend/amplify-meta.json) export GRAPHQL_API_NAME=$(aws appsync get-graphql-api --api-id $GRAPHQL_API_ID --region $AWS_REGION | jq -r '.graphqlApi.name') export GRAPHQL_ENDPOINT=$(sed -n 's/.*"aws_appsync_graphqlEndpoint": "\(.*\)".*/\1/p' src/aws-exports.js) export UNAUTH_ROLE=$(jq -r '.providers.awscloudformation.UnauthRoleName' amplify/#current-cloud-backend/amplify-meta.json) export ID_POOL_ID=$(sed -n 's/.*"aws_cognito_identity_pool_id": "\(.*\)".*/\1/p' src/aws-exports.js) export ID_POOL_NAME=$(jq -r '.auth[(.auth | keys)[0]].output.IdentityPoolName' ./amplify/#current-cloud-backend/amplify-meta.json) export DEPLOYMENT_BUCKET_NAME=$(jq -r '.providers.awscloudformation.DeploymentBucketName' ./amplify/#current-cloud-backend/amplify-meta.json) export STACK_NAME=$(jq -r '.providers.awscloudformation.StackName' ./amplify/#current-cloud-backend/amplify-meta.json) aws cognito-identity update-identity-pool --identity-pool-id $ID_POOL_ID --identity-pool-name $ID_POOL_NAME --allow-unauthenticated-identities --region $AWS_REGION aws appsync update-graphql-api --api-id $GRAPHQL_API_ID --name $GRAPHQL_API_NAME --authentication-type AWS_IAM --region $AWS_REGION
-
Install the Lambda dependencies and deploy the backend with SAM:
cd ./sam-app/get-movie;npm install; cd ../.. sam package --template-file ./sam-app/template.yaml --s3-bucket $DEPLOYMENT_BUCKET_NAME --output-template-file packaged.yaml --region $AWS_REGION export STACK_NAME_SAM="$STACK_NAME-lambda" sam deploy --template-file ./packaged.yaml --stack-name $STACK_NAME_SAM --capabilities CAPABILITY_IAM --parameter-overrides unauthRole=$UNAUTH_ROLE graphqlApi=$GRAPHQL_API_ID graphqlEndpoint=$GRAPHQL_ENDPOINT tmdbApiKey=$TMDB_API_KEY --region $AWS_REGION
-
Execute the following command to access and query your API directly from the AWS Console (or manually go to the AWS AppSync Console, access your API and open the
Queries
section):amplify console ? Please select the category or provider: api ? Please select from one of the below mentioned services: GraphQL
-
Execute each one of these 5 mutations to create the data sctructure that will collect and store votes in the Reviews table:
mutation {
type1: createReviews(
input: { id: 1, type: "love", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type2: createReviews(
input: { id: 2, type: "like", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type3: createReviews(
input: { id: 3, type: "meh", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type4: createReviews(
input: { id: 4, type: "unknown", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
type5: createReviews(
input: { id: 5, type: "hate", votes: 0, topMovie: "N/A", topVotes: 0 }
) {
id
type
votes
topMovie
topVotes
}
}
-
Finally, execute the following command to install your project package dependencies and run the application locally:
amplify serve
-
Open different browsers and test realtime subscriptions. Alternativelly publish your application and use the public link:
amplify add hosting amplify publish
To clean up the project, you can simply delete the stack created by the SAM CLI:
aws cloudformation delete-stack --stack-name $STACK_NAME_SAM --region $AWS_REGION
and use:
amplify delete
to delete the resources created by the Amplify CLI.
This sample code is made available under a modified MIT license. See the LICENSE file.