DEV Community

Cover image for How to build Serverless GraphQL API using AWS AppSync

How to build Serverless GraphQL API using AWS AppSync

What is GraphQL?

GraphQL is a query language for APIs which provides a complete and understandable description of the data in the API. GraphQL APIs give the exact data that the client wants, nothing more or less.

GraphQL is fast and flexible to use as compared to REST. GraphQL allows clients to decide what data to be returned unlike servers in REST. GraphQL reduces the number of HTTP requests since it can get you all the data required by your app in a single request. According to official documentation, apps using GraphQL can be quick even on slow mobile network connections.

GraphQL Operations

  1. Query - Used to fetch the data from the GraphQL API, same as GET request
  2. Mutation - Used to manipulate the data, same as CREATE, UPDATE, DELETE
  3. Subscription - Used to listen or subscribe to the changes to the data

What is AppSync?

AWS AppSync is a fully managed, serverless GraphQL API service offered by Amazon Web Services. AppSync allows developers to build GraphQL APIs without much hassle; it takes care of the parsing and resolution of requests.

It also natively supports integration with other AWS services like AWS Lambda, NoSQL and SQL databases, and HTTP APIs to gather backend data for the API.

What are we going to build?

We will build a GraphQL API using AWS AppSync to perform CRUD operations. For example, we will make an API that will allow us to create, read, update and delete a blog. We will use DynamoDB to store our blog data to achieve the functionality of the CRUD API we will use Lambda. To configure our resources we will use Serverless Framework.

Initialising the project

First of all, create an empty directory and we will create a new serverless project in this directory. You can use the following command to do that.

serverless create --template aws-nodejs

The above command will create a new serverless project for you from scratch and you can find the serverless.yml file in the editor. This file is the heart of the project, where we will define all our infrastructure.

This is how the serverless.yml file will look after all the resources are defined. I will explain each section of this file further.

Firstly, start defining the basics like region, stage, and global configuration variables in the provider section.



provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221
  region: ${env:REGION, 'ap-south-1'}
  stage: ${opt:stage, 'dev'}
  timeout: 30



Enter fullscreen mode Exit fullscreen mode

Then, we define global-level environment variables, as defined in the image below.



  # Environment variables
  environment:
    STAGE: ${self:provider.stage}
    REGION: ${self:provider.region}
    SERVICE_NAME: ${self:service}-${self:provider.stage}
    DYNAMODB: ${self:service}-${self:provider.stage}


Enter fullscreen mode Exit fullscreen mode

IAM role statements

Since we are going to use DynamoDB to store the data and it will be integrated with the lambda function, we will need to define IAM role statements to give permission to the lambda function to access our DynamoDB table.



# IAM statements
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:GetItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
        - dynamodb:PutItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB}"
    - Effect: Allow
      Action:
        - lambda:invokeFunction
      Resource: "*"


Enter fullscreen mode Exit fullscreen mode

serverless-appsync-plugin

serverless-appsync-plugin allows us to deploy AppSync API without much hassle, it provides a lot of configurations to set up your API on AppSync.



plugins:
  - serverless-appsync-plugin


Enter fullscreen mode Exit fullscreen mode

Lambda Functions



functions:
  createBlog:
    handler: createBlog/index.handler
    name: createBlog-${self:provider.stage}
  getBlog:
    handler: getBlog/index.handler
    name: getBlog-${self:provider.stage}
  updateBlog:
    handler: updateBlog/index.handler
    name: updateBlog-${self:provider.stage}
  deleteBlog:
    handler: deleteBlog/index.handler
    name: deleteBlog-${self:provider.stage}


Enter fullscreen mode Exit fullscreen mode

Now, it's time to set up the appsync configuration provided by serverless-appsync-plugin, this plugin has a lot of configurations available, in the below code snippet you can find some of them. In the custom section of the serverless.yml file, we can define the configurations.

To know more about what each of these configuration parameters does, head over to this link.



custom:
appSync:
name: appsync-crud-api
schema: schema.api.graphql
authenticationType: API_KEY
apiKeys:
- apiKey
dataSources:
- type: AWS_LAMBDA
name: createBlog
description: 'Lambda'
config:
functionName: createBlog

- type: AWS_LAMBDA
name: getBlog
description: 'Lambda'
config:
functionName: getBlog
- type: AWS_LAMBDA
name: updateBlog
description: 'Lambda'
config:
functionName: updateBlog
- type: AWS_LAMBDA
name: deleteBlog
description: 'Lambda'
config:
functionName: deleteBlog

Enter fullscreen mode Exit fullscreen mode




DynamoDB Table

To store the blog data we are using the dynamodb table which can be configured like the below:



resources:
Resources:
BlogsTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB}

Enter fullscreen mode Exit fullscreen mode




GraphQL Schema

Every graphql API needs a schema where we define all the operations(query, mutation, subscription). We will need to create a file named schema.api.graphql. This same file we have referred to in the appsync plugin configuration is in the custom section. The file should look something like this:



schema {
query: Query
mutation: Mutation
}

type Query {
# Query for blog details
getBlog(id: ID!): Blog
}

type Mutation {
# Create blog
createBlog(input: CreateBlogInput!): AWSJSON

# Update blog
updateBlog(input: UpdateBlogInput!): AWSJSON

# delete blog
deleteBlog(id: ID!): AWSJSON
Enter fullscreen mode Exit fullscreen mode

}

input UpdateBlogInput {
id: ID!
title: String
blogUrl: String
author: String
publicationDate: AWSDate
}

input CreateBlogInput {
title: String!
blogUrl: String!
author: String!
publicationDate: AWSDate!
}

type Blog {
id: ID
title: String
blogUrl: String
author: String
publicationDate: AWSDate
}

Enter fullscreen mode Exit fullscreen mode




Lambda Function Code

Now it's time to move towards lambda functions, which will act as a resolver for the API. Hence the name, "Lambda Resolvers". As you can see in the image below, I have created a folder for each of the lambda functions which we defined in the functions section in the serverless.yml file.

All four lambdas just perform very simple dynamodb CRUD operations using dynamodb DocumentClient() from aws-sdk. I won't explain the lambda code since it's really straightforward. You can head over to this repository and find the code.

Lambda Folder Structure

If you have followed until now, then it's time to deploy our service 🚀.

Use serverless deploy to deploy all of your defined resources to the aws cloud. This will give you the deployed API URL and API_KEY in the console which can be used by the client application.

Testing the GraphQL API

Once your deployment is successful, you'll see something like this in the AppSync console. You'll see a tile with the name you have given to your API.

Testing in AppSync Console

Click on the tile and you'll see another interface, then in the left nav click on Queries. You should see the following interface where you will find all the CRUD operations we have defined in our schema.api.graphql file.

In the mutations section, you'll find createBlog, updateBlog, and deleteBlog, and in the queries section, you'll find getBlog.

You can then test the createBlog mutation by entering some data and hitting the play button on the top should give you the success response by returning the created blog's data in the rightmost window.

Testing in AppSync Console

By doing the same steps, you can test the other operations as well.

Aaaand 🥁, we are done with the whole backend side of things. We just created an API for a simple blog application.

That's all for this blog, if you liked it do not forget to react to the blog. Thanks for reading and following along, Peace ☮✌️.

Feel free to reach out to me:

GitHub - https://github.com/iabhishek07
Twitter - https://twitter.com/abhishekrwagh
LinkedIn - https://www.linkedin.com/in/iamabhishek21/
Email - waghabhi21@gmail.com

Top comments (2)

Collapse
 
berviantoleo profile image
Bervianto Leo Pratama

Awesome! Thank you for the post. Currently, I'm learning the App Sync, and this post is helpful.

Collapse
 
iabhishek07 profile image
Abhishek Rajendra Wagh

Thank you so much @berviantoleo. I am glad this post could be of any help to you.