Deploy AppSync GraphQL API with SAM | part one
In this post, we will use AWS SAM, the Serverless Application Model, to deploy your AppSync GraphQL API. Serverless computing is the result of the need for adaptable, scalable, and effective solutions in light of the changing digital landscape, and AWS AppSync is leading the way in this transformation.
AWS AppSync, which uses GraphQL as its query language, makes it easier to create strong APIs for your apps. When combined with AWS SAM, it achieves new levels of efficiency by offering a standardized way to define serverless applications. This article is intended to empower you, whether you are a seasoned developer trying to improve your GraphQL abilities or a newbie intrigued about the power of serverless computing.
To clarify the complexities of deployment, we will examine the core ideas behind AWS SAM and AppSync throughout this investigation. Every stage is thoroughly explained to guarantee a seamless and instructive experience, from basic setup to customizing your GraphQL API and ultimately deploying using AWS SAM. Await the moment when you see how AWS AppSync and SAM work together to unleash your serverless applications’ full potential.
So buckle in, and let’s explore the deployment landscape while we uncover the potential of AppSync and SAM. Together, let’s change the way you think about serverless architecture and bring in a brand-new wave of creativity!
Architecture
This solution will start with a basic GraphQL schema and concentrate more on the folder structure and code to provide a scalable and easily maintained application. To make things as simple as possible, resolvers will be written in JavaScript, and DynamoDB will be used with a direct AppSync integration.
AWS AppSync simplifies the development of scalable and secure APIs by providing a managed GraphQL service. When working with JavaScript resolvers and DynamoDB direct integration in AppSync, you’re combining the power of GraphQL for API development, JavaScript for defining resolvers, and DynamoDB for data storage.
Here’s a breakdown of how this combination works:
1. GraphQL Schema Definition:
- Start by defining your GraphQL schema, specifying types, queries, mutations, and subscriptions.
- GraphQL is a query language that enables clients to request only the data they need, promoting efficient data fetching.
2. JavaScript Resolvers:
- Resolvers are functions that handle the actual execution of GraphQL operations.
- With AppSync, you can use JavaScript to define these resolvers, which are responsible for fetching and processing the data.
- Resolvers map to the fields defined in your GraphQL schema and are executed for queries, mutations, and subscriptions.
3. DynamoDB Direct Integration:
- DynamoDB, a NoSQL database service on AWS, can be directly integrated into your GraphQL schema through AppSync.
- This integration eliminates the need for custom server-side logic, making your architecture more straightforward and scalable.
- Define the data source in your AppSync API to connect to your DynamoDB tables.
4. Resolving GraphQL Queries/Mutations:
- When a GraphQL query or mutation is made, the corresponding resolver functions are triggered.
- JavaScript resolvers interact with DynamoDB tables directly through the defined data sources, executing read or write operations.
- AppSync manages the communication between the GraphQL API and the underlying data sources, handling authentication and authorization transparently.
5. Security and Authorization:
- AppSync provides fine-grained control over security and authorization through its resolver mapping templates.
- Leverage DynamoDB IAM roles to control access to your data at the database level.
6. Scaling and Serverless:
- AppSync is serverless, meaning it automatically scales based on demand.
- DynamoDB is also a serverless database service, automatically scaling to accommodate varying workloads.
By combining AppSync, JavaScript resolvers, and DynamoDB direct integration, you create a powerful and scalable architecture for building GraphQL APIs. This approach simplifies development, reduces the need for custom server-side code, and ensures real-time capabilities, making it an excellent choice for modern applications.
Code Base
As usual, you can find the final version of the code in the GitHub repository.
Let’s start to take a look at the template.yaml
file:
Parameters
There is nothing fancy regarding the parameters section: the APIName
parameter definition allows users to customize the name of the AppSync GraphQL API when deploying the SAM template
Parameters:
APIName:
Type: String
Description: The name for the AppSync GraphQL API to be created.
Default: Ticket API
Resources
AppSync GraphQL API definition, you can find the CloudFormation documentation of all the AppSync resources here:
AppSyncTicketAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
Name: !Sub ${APIName}
AuthenticationType: API_KEY
AWS::AppSync::GraphQLApi
resource specifies that an AWS AppSync GraphQL API will be created with a name defined by the parameter APIName
and AuthenticationType
by using the API_KEY AppSync feature.
The API Key has been defined by the following resource:
AppSyncApiKey:
Type: AWS::AppSync::ApiKey
Properties:
ApiId: !GetAtt AppSyncTicketAPI.ApiId
The ApiId
properties property is set to the ApiId
attribute of the AppSyncTicketAPI
resource using the !GetAtt
intrinsic function(if you want to know more about intrinsic functions follow this link). This indicates that the API Key is associated with the specified AppSync API.
The schema is specified by the following resource:
AppSyncTicketSchema:
Type: AWS::AppSync::GraphQLSchema
Properties:
ApiId: !GetAtt AppSyncTicketAPI.ApiId
DefinitionS3Location: ./src/schema.graphql
One of the advantages of using SAM is that you can define the schema in a local file without the need to manually upload it on S3 or hardcode the GraphQL schema inside the CloudFormation stack. SAM will upload the file and update the location folder to retrieve the correct GraphQL schema during the CloudFormation deployment operation.
Take a look inside the S3 bucket SAM created for you and the Template section in the CloudFormation console:
The goal here is to avoid something awful like this:
AppSyncGraphQLSchema:
Type: AWS::AppSync::GraphQLSchema
DependsOn: AppSyncGraphQLApi
Properties:
ApiId: !GetAtt AppSyncGraphQLApi.ApiId
Definition: |
type Ticket {
id: ID!
date: AWSDateTime
band: String
place: String
}
type Query {
getAllTickets: [Ticket]
getSingleTicket(id: ID!): Ticket
}
type Mutation {
createSingleTicket(
date: AWSDateTime
band: String
place: String
): Ticket
}
...
🤢 🤮
It is far better to have a separate file with schema as you can find inside the repo I shared: https://github.com/stech-world/simple-appsync-graphql-api/blob/main/src/schema.graphql
type Ticket {
id: ID!
date: AWSDateTime
band: String
place: String
}
type Query {
getAllTickets: [Ticket]
getSingleTicket(id: ID!): Ticket
}
type Mutation {
createSingleTicket(
date: AWSDateTime
band: String
place: String
): Ticket
}
This allows you also to use extensions for the syntax highlight and auto-completion for GraphQL e.g. https://marketplace.visualstudio.com/items?itemName=orsenkucher.vscode-graphql if, like me, you use VSCode.
In this post, I won’t explain in detail the GraphQL schema, I want to focus more on the code base for an AppSync project.
Shortly, the schema defines a simple ticketing system with three main types: Ticket
, Query
, and Mutation
.
- Ticket Type:
Ticket
represents a ticket entity with fields:id
: An ID, required and unique.date
: A date in AWS DateTime format.band
: A string representing the band associated with the ticket.place
: A string representing the place where the event associated with the ticket takes place. - Query Type:
Query
type defines two queries:getAllTickets
: Retrieves an array ofTicket
objects.getSingleTicket(id: ID!)
: Retrieves a singleTicket
object based on
the provided ID. - Mutation Type:
Mutation
type defines one mutation:createSingleTicket
: Creates a newTicket
by providing values fordate
,band
, andplace
. It returns the createdTicket
object.
In summary, this GraphQL schema allows querying for tickets, retrieving all tickets, fetching a single ticket by ID, and creating a new ticket. The Ticket
type encompasses the properties of a ticket, while the Query
and Mutation
types provide the API operations to interact with the ticketing system. The schema is designed for basic CRUD (Create, Read, Update, Delete) operations on ticket entities.
That’s all for the first part of this post. Follow the second part in which I will explain how to create Dynamo and the remaining AppSync resources e.g. resolvers, datasource, and functions.
See you in the next post!