These GraphQL API examples show end-to-end implementations of a simple application using a serverless approach that includes CI/CD pipelines, automated testing, and workload observability. They implement same API as in the set of REST API samples and follow the same approach to CI/CD, observability, etc.
The examples include multiple implementations of the same application using a variety of development platforms and infrastructure as a code approaches. The patterns here will benefit beginners and seasoned developers looking to improve their applications by automating routine tasks.
There are various blog posts and code examples for serverless GraphQL APIs available. However, most of them do not go beyond the first steps of implementing business logic and access controls. These examples dive deeper, including:
- CI/CD pipelines containing automated testing
- manual approval steps before updates go live
- automated alerts and dashboards for workload observability
- AWS AppSync logging and AWS X-Ray support
The API uses AWS AppSync as a front door. Every new client is first required to use their credentials to authenticate with Amazon Cognito and retrieve an identity token. They must then pass this as a bearer token in the Authorization header with each subsequent request. The AWS AppSync inspects this token and allows or denies the query or mutation specified in the client request.
Access to the data depends on the user's role and identity. All users have read access to the Locations and Resources associated with Locations. They also have read/write access to their own Bookings. Administrative users have read/write access to all Locations, Resources, and Bookings. User status (regular vs. administrative) is defined by their membership in the API administrators’ group in Cognito User Pool.
AWS AppSync uses Amazon DynamoDB Resolvers to implement application business logic. Data is persisted in DynamoDB tables, one table per API resource.
GraphQL exposes operations via a schema that defines the capabilities of an API. A schema is comprised of types, which can be root types (query, mutation, or subscription) or user-defined types. The following is GraphQL schema for the API, that defines Location, Resources, Booking along with the queries and mutations:
For more guidance on how to design a GraphQL schema for an API, take a look at this documentation article.
These examples create the following resources in your AWS account:
- AWS AppSync endpoint that serves all API requests
- DynamoDB tables to store data
- AWS AppSync logs stream in Amazon CloudWatch Logs
- Amazon SNS topic for the alarms
- AWS AppSync 5XX errors alarm
- Throttling alarms for all DynamoDB tables
- CloudWatch Dashboard with AWS AppSync and DynamoDB metrics pre-configured
Each example implements logging using CloudWatch Logs, configures CloudWatch alerts, and creates a CloudWatch dashboard. X-Ray distributed tracing is enabled whenever it is supported. AWS AppSync logging is enabled and AWS Serverless Application Model (AWS SAM) templates override the default log stream to set the retention period to 7 days.
For better manageability and cost visibility , use tags - key and value pairs that act as metadata for organizing your AWS resources. You may need to activate AWS cost allocation tags for use them in AWS Cost Explorer, see documentation for more details. Each example uses a tag named "Stack" for the resources it creates. You can use it in the Cost Explorer or cost allocation reports as described in the documentation article linked above. For more information on tagging AWS resources, see documentation.
Check the AWS CloudFormation outputs of your deployment to see the CloudWatch dashboard URL, references to the AWS AppSync logs stream, and alarms topic in SNS.
-
To receive alerts, you will need to create a subscription for the SNS topic. See documentation for instructions.
-
The dashboards are operational immediately, follow the URL in the CloudFormation outputs:

Each example includes integration tests that are run automatically by the CI/CD pipeline. See the documentation of a particular example for the instructions on how to run tests manually.
Each example provides two ways to deploy resources - manual and CI/CD pipeline driven.
If you choose to deploy components manually, you will need to deploy a shared Cognito stack. Don't forget to update the parameter values in the templates or code accordingly if you used a shared stack name different from the one used in documentation.
When you choose to use a CI/CD pipeline to deploy resources, you will create a code repository and two environments - staging and production. Each of the environments will have all necessary resources, including their own shared Cognito stacks. The build stage will automatically perform all unit tests. Staging will run integration tests before stopping for a manual production deployment approval step.
See individual example documentation for detailed instructions on how to deploy the example manually or create a CI/CD pipeline.
Check these implementations of the example API for more details and resources to explore.
- javascript-appsync-sam-js - this GraphQL API implementation uses Node.js, AWS AppSync with JavaScript resolvers, AWS SAM, CloudFormation
- javascript-appsync-sam-vtl - this GraphQL API implementation uses Node.js, AWS AppSync with Apache Velocity Template Language (VTL) resolvers, AWS SAM, CloudFormation
- python-appsync-sam-vtl - this GraphQL API implementation uses Python, AWS AppSync with Apache Velocity Template Language (VTL) resolvers, AWS SAM, CloudFormation
- shared - resources shared across the projects, such as Cognito stack.
