Setting Up Your Environment for a Serverless GraphQL API on AWS Lambda
Tags: graphql, aws, typescript, serverless
Published: 2023-05-02 16:00:00

Serverless is cool and can save you a lot of money, because you do not have servers running all the time, only when someone wants to use your service - an that is also good for our environment, isn't it? But when you want to start with serverless the amount of documentation might be really overwhelming and you might not know where to start. This blog posts series should help you getting an easy entry into the topic. It will cover the process of constructing a fully serverless GraphQL API, which will include queries, mutations, and subscriptions. The deployment of this API will be accomplished through the use of the AWS CDK. 

In this first part we will do the initial setup using the AWS CDK and build an initial version with the AWS Api Gateway and AWS Lambda.

## Getting Started
First of all we will be doing everything as code so that it can be reused and easily adapted to future needs. We assume you already have an AWS account and setup your AWS CLI with your credentials. If you did not do this yet, create a account following the [AWS User Guide](https://docs.aws.amazon.com/SetUp/latest/UserGuide/setup-AWSsignup.html) and setup your CLI following the [Getting started with the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) and the user guide on [Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-using-profiles).

So lets start setting up our project and creating our lambda function with the CDK.

### Create a Workspace and your Project
First things first, setup the repo. We will be using nx to create a monorepo to have all our code in one place. Run `npx create-nx-workspace@latest serverless-hero --preset=ts`  and follow the steps and confirm the request to install the necessary packages. Now we have our repo let's setup our package: `npm i @nx/node && nx g @nx/node:application serverless-api`. When nx asks you which framework to install choose none.

### Install the AWS CDK
For being able to use the CDK we first need to install it, for this run `npm i -D aws-cdk-lib` in the root of your newly created project.

### Create the CDK App
For creating our cdk app as an nx package we will use the [nx-cdk](https://github.com/cubesoftorg/nx/tree/main/packages/nx-cdk) package. First install the package with `npm i -D @nrwl/workspace && npm i -D @cubesoft/nx-cdk` and then you can create your cdk app with `nx g @cubesoft/nx-cdk:nx-cdk serverless-cdk`. This creates a new package called serverless-cdk for us, for finishing the setup we need to provide the correct environment values in the serverless-cdk/src/app.ts file for account and region. And make sure the line in which you put it is uncommented. Then we need to run `nx bootstrap serverless-cdk --profile <profile>` (the profile parameter is only required if you have multiple profiles in your aws credentials file) and we are ready to go.

## Defining the CDK Stack
Now that we have setup everything we can start with the interesting stuff. Let's have a quick look an what we want to achieve.

![API Gateway Lambda Connection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1d2dpa28wwsq0lk54l3.png)
So there are two main parts we need to setup: 
1. The API Gateway
2. The Lambda Function


### The API Gateway
Let's start with the fun part, setting up the API Gateway
We will create a HTTP API because this comes at lower costs than the REST API, and we do not need the additional features of the REST API however if you are interested in the differences between both you can read more [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html).

In the serverless-cdk/src/lib/my-stack.ts you can add the add the HttpApi with the required configurations. Btw. you can also rename the my-stack file and the name of the Stack itself, I renamed it to ServerlessStack, but make sure you correctly reference it in your app.ts file.

``` typescript
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

import { CorsHttpMethod, HttpApi } from '@aws-cdk/aws-apigatewayv2-alpha';
export class ServerlessStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const api = new HttpApi(this, 'httpAPI', {
      apiName: `http-api`,
      corsPreflight: {
        allowHeaders: ['Content-Type', 'Authorization'],
        allowMethods: [CorsHttpMethod.GET, CorsHttpMethod.POST],
        allowOrigins: ['*'],
      },
    });
  }
}
```
Make sure to install the `@aws-cdk/aws-apigatewayv2-alpha` package.

To ensure that the API can later be called via a browser we need to provide the corsPreflight options, because we also want to also add authorisation functionality later we provide a specific 'Authorization' header, but you can add even more if you need them.

## The Lambda Function
Now that we have the Gateway we can create the Lambda function. For this blog post we will create a really simple Lambda Function and we will focus on the GraphQL part in the next blog post.

``` typescript
import { Duration, Size } from 'aws-cdk-lib';
import { Architecture, Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';

const lambda = new Function(this,'api-handler', {
    runtime: Runtime.NODEJS_18_X,
    handler: 'handler',
      code: lambda.Code.fromInline(`
    exports.handler = async function(event) {
      console.log("Hello, CDK!");
      return {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
      };
    }
  `),
    memorySize: Size.gibibytes(1).toMebibytes(),
    architecture: Architecture.ARM_64,
    logRetention: RetentionDays.ONE_MONTH,
    timeout: Duration.seconds(5)
});
```

This creates the Lambda Function, now we need to connect it with the API Gateway, so that someone can call it. For this you need to install `@aws-cdk/aws-apigatewayv2-integrations-alpha`

``` typescript
import { HttpApi, HttpMethod } from '@aws-cdk/aws-apigatewayv2-alpha';
import { HttpLambdaIntegration } from '@aws-cdk/aws-apigatewayv2-integrations-alpha';

const readIntegration = new HttpLambdaIntegration('apiReadIntegration', lambda);
const writeIntegration = new HttpLambdaIntegration('apiWriteIntegration', lambda);

api.addRoutes({
   integration: readIntegration,
   methods: [HttpMethod.GET],
   path: '/graphql'
});
api.addRoutes({
   integration: writeIntegration,
   methods: [HttpMethod.POST],
   path: '/graphql'
});
```

## Deploy your stack
Finally, you can deploy your CDK stack using the command `nx deploy serverless-cdk`. And there you are, you have just created and deployed your first lambda function on AWS. When you visit your AWS Console and go to the AWS API Gateway you can find your invoke url which you can use to check if your deployed api works. Just open it in your browser <Invoke-Url>/graphql and you should see the text `"Hello from Lambda!"`. You made it!


You can find my sample repo [here](https://github.com/TanjaBayer/Zero-to-Serverless-Hero)