Skip to content
Go back

Creating a GraphQL API using AWS AppSync and CDK

Edit page

How to create a GraphQL CRUD backend using an IaC approach in a timely, effective and flexible manner.

post-cover

As Software Engineers, we sometimes need to provide quick solutions to trivial problems. When that happens, we face the challenge of delivering what the product or the business needs in a timely manner while not creating tech debts, which this kind of situation often leads us to.

In this session, an effective and flexible solution for building an entire GraphQL API with all the CRUDs needed will be introduced, keeping the developer in control of CI/CD, security, and other aspects using AWS CDK. The goal is to code as little as possible and spend the energy on functions or features that MUST be customized.

TL;DR

Clone the tutorial repo, customize the GraphQL Schema and deploy.

What we’re going to build?

architecture-diagram

We will use AWS AppSync to create a complete GraphQL CRUD backend. Under the hood, GraphQL queries and mutations, Resolvers functions, DynamoDB tables, and an API Endpoint will be created without intervention. However, you will be able to access all outputs and use them in other stacks of your project.

Initializing the project

To get started, we’ll use the AWS CDK CLI to bootstrap our project. If you need to install it, you can find the instructions here.

npx cdk init sample-app --language typescript

Installing AWS Amplify libraries

We need to use an L3 CDK Construct that wraps the behaviour of the Amplify GraphQL Transformer and enables support to the Amplify GraphQL Directives.

npm install @aws-amplify/graphql-api-construct

Designing the GraphQL Schema

Then, we are going to design our GraphQL Schema. This schema was created for demonstration purposes only. I’ve used AWS AppSync Directives like @model, @auth, @belongsTo and @hasMany. Further details can be found here.

type Movie @model(subscriptions: null) @auth(rules: [{ allow: public }]) {
  id: ID!
  name: String!
  year: Int!
  rating: Float!
  poster: String!
  tags: [String]
  studio: Studio! @belongsTo
}

type Studio @model(subscriptions: null) @auth(rules: [{ allow: public }]) {
  id: ID!
  name: String!
  movies: [Movie] @hasMany
}

Placing the schema in the lib folder

The schema.graphql file should be placed in the lib folder. If you want to put it into another folder, please update the stack definition introduced in the next step.

schema-place

Writing the CDK stack

Modify the CDK Stack class to create the AWS AppSync API. This transformer has many options and customizations; the complete documentation is here.

export class AwsCdkAppsyncStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const amplifyApi = new AmplifyGraphqlApi(this, "aws-cdk-appsync-api", {
      definition: AmplifyGraphqlDefinition.fromFiles(
        path.join(__dirname, "schema.graphql")
      ),
      authorizationModes: {
        defaultAuthorizationMode: "API_KEY",
        apiKeyConfig: {
          expires: Duration.days(30),
        },
      },
    });
  }
}

Deploying

We’re set. Now, we can deploy our project. Before completing this step, you should configure your AWS CLI. The instructions are here.

cdk deploy

Check out the Outputs values in the terminal. We’ll need them in the next step.

Outputs:
AwsCdkAppsyncStack.amplifyApiModelSchemaS3Uri =
AwsCdkAppsyncStack.awsAppsyncApiEndpoint =
AwsCdkAppsyncStack.awsAppsyncApiId =
AwsCdkAppsyncStack.awsAppsyncApiKey =
AwsCdkAppsyncStack.awsAppsyncAuthenticationType = API_KEY
AwsCdkAppsyncStack.awsAppsyncRegion = us-east-1
Stack ARN:

You can see all generated queries, mutations, VTL functions, DynamoDB tables over the AWS console:

dynamodb-tables DynamoDB Tables

resolvers Resolvers

queries-mutations Queries and Mutations

Running Mutations & Queries

Let’s test what we’ve just created! Set up your favourite GraphQL client to access the brand-new API. From the step above, you should get awsAppsyncApiEndpoint and awsAppsyncApiKey.

If you don’t have a favourite GrapQL client, use GraphiQL, Postman, or the AWS Console (AWS AppSync > APIs > your-api-name > Queries).

If you are using a post request, set the API Key correctly. Like this:

curl --location '{awsAppsyncApiEndpoint}' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: {awsAppsyncApiKey}' \

Testing

mutation CreateMovieMutation(
  $name: String!
  $poster: String!
  $rating: Float!
  $year: Int!
  $studioMoviesId: ID
  $tags: [String]
) {
  createMovie(
    input: {
      name: $name
      poster: $poster
      rating: $rating
      year: $year
      studioMoviesId: $studioMoviesId
      tags: $tags
    }
  ) {
    id
  }
}

create-movie Create Mutation example

query GetMovieQuery($id: ID!) {
  getMovie(id: $id) {
    id
    name
    year
    rating
    poster
    tags
    studio {
      name
    }
  }
}

query-movie Get Query example

Conclusion

As demonstrated here, building a complete GraphQL API with all the CRUD mutations is a nice to have in a Software Engineer’s tool belt. The main effort here should be designing a well-shaped GraphQL schema with the product team rather than writing lambda functions and VTL files from scratch. By using IaC (AWS CDK), you are able to keep the solution compliant with all the company’s devops rules and security policies. At the same time, you should spend a few hours building a complete backend solution and putting it alive. You can find the code from this tutorial on my GitHub.

Going further

In the next sessions, we will discuss options for controlling authorization using AWS Cognito User Pools and API Keys.


Edit page
Share this post on:

Previous Post
Building a Smart URL Content Summarizer with AWS Bedrock