← Return home

Serverless GraphQL server on AWS Lambda

Serverless environments such as AWS Lambda allows you to run your server-side code without obtaining/maintaining/paying a dedicated server. You don’t have to care about OS/software updates and you can focus on your application code. Also, you pay as you go!

In this article we will see how to run a GraphQL server on AWS Lambda step by step.

Achitecture Diagram

We are going to use:

  • NodeJS
  • Lambda & API Gateway
  • AWS cli
  • CloudFormation
  • S3 bucket

Setup the NodeJs project

At the time of this writing, the latest NodeJs version that is supported in the AWS Lambda environment is nodejs12.x. So, make sure that you have installed a v12.X version in your system. We will use nvm for this.

1~ $ nvm install v12.7.0
2~ $ nvm use v12.7.0

The Lambda function

We will use the NodeJS library apollo-server-lambda which is the AWS Lambda integration of GraphQL Server.

1~ $ npm init
2~ $ npm i apollo-server-lambda

graphql.js

1const { ApolloServer: ApolloServerLambda, gql } = require('apollo-server-lambda');
2
3const typeDefs = gql`
4  type User {
5    id: ID
6    name: String
7  }
8  type Query {
9    me: User
10  }
11  type Mutation {
12    log(message: String): String
13  }
14`;
15
16const resolvers = {
17  Query: {
18    me: () => {
19      return { id: 1, name: 'John' };
20    }
21  },
22  Mutation: {
23    log: (parent, args) => {
24      const { message } = args;
25      const info = `logging: ${message}`;
26      console.log(info);
27      return info;
28    }
29  }
30};
31
32const server = new ApolloServerLambda({
33  typeDefs,
34  resolvers,
35  context: ({ event, context }) => ({
36    functionName: context.functionName,
37    headers: event.headers
38  }),
39  playground: {
40    endpoint: '/Prod/graphql'
41  },
42  introspection: true
43});
44
45exports.handler = server.createHandler({
46  cors: {
47    origin: '*',
48    credentials: true
49  }
50});

CloudFormation

CloudFormation allows you to define AWS resources in code. In the following template we define a Lambda function and an API Gateway by using the AWS::Serverless::Function resource type:

template.yml

1AWSTemplateFormatVersion: '2010-09-09'
2Transform: AWS::Serverless-2016-10-31
3Globals:
4  Function:
5    Timeout: 6
6
7Resources:
8  GraphQLFunction:
9    Type: AWS::Serverless::Function
10    Properties:
11      CodeUri: .
12      Handler: graphql.handler
13      Runtime: nodejs12.x
14      Events:
15        GraphQL:
16          Type: Api
17          Properties:
18            Path: /graphql
19            Method: any
20      Environment:
21        Variables:
22          NODE_ENV: production
23
24Outputs:
25  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
26  GraphQLApi:
27    Description: "API Gateway endpoint URL for Prod stage for GraphQL lambda function"
28    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/graphql"
29    Export:
30      Name: GraphQLApi

AWS cli

In the next steps we will use the AWS cli to deploy our app. Make sure that you have configured the AWS cli first by running aws configure.

S3 Bucket

We need to create a S3 bucket to host the code of the Lambda function. Replace {your-bucket-name} with a universal unique S3 bucket name of your choice.

1~ $ aws s3 mb s3://{your-bucket-name} --region eu-central-1

Package your code

The below command zips & uploads your code in your S3 bucket. Also, it exports the template-output.yml file which will be used in the next step.

1~ $ aws cloudformation package \
2         --template-file template.yml \
3         --output-template-file template-output.yml \
4         --s3-bucket {your-bucket-name}

Deploy your code

The following command will deploy our code to our Lambda function. You can replace the serverless-graphql with your CloudFormation stack name of your choice.

1~ $ aws cloudformation deploy \
2         --template-file template-output.yml \
3         --stack-name serverless-graphql \
4         --capabilities CAPABILITY_IAM \
5         --no-fail-on-empty-changeset
6
7waiting for changeset to be created..
8Waiting for stack create/update to complete
9
10Successfully created/updated stack - serverless-graphql

Export the URL of the GraphQL server

The final step is to get the exported GraphQL URL:

1~ $ aws cloudformation list-exports \
2         --query "Exports[?Name=='GraphQLApi'].Value"
3
4[
5    "https://k6hl3sdw0b.execute-api.eu-central-1.amazonaws.com/Prod/graphql"
6]

We are live!

We are live at 🚀 https://k6hl3sdw0b.execute-api.eu-central-1.amazonaws.com/Prod/graphql 🚀.

At this link we can play with the GraphQL Playground which is a graphical, interactive, in-browser GraphQL IDE that allows you to explore/test visually the avaialble GraphQL queries, mutations and subcriptions.

Screenshot 2020-11-25 at 4.49.48 AM

Also, let’s test it from the command line:

1$ curl \  
2    -X POST \  
3    -H "Content-Type: application/json" \  
4    --data '{ "query": "{ me { id name } } "}' \  
5    https://k6hl3sdw0b.execute-api.eu-central-1.amazonaws.com/Prod/graphql
6    
7{"data":{"me":{"id":"1","name":"John"}}}

Nice! It works as expected!

The complete code of this post is at my Github repo!

For more tech posts follow me on Twitter at @johndusaitis!

Thanks for reading!

Would you like to get updates for new stories?