Setting up a Production GraphQL Server — Part 1: The Server

Photo by Jordan Harrison on Unsplash

At JetClosing, we recently released Version 2 of our app. For this release, we developed a whole new backend service that uses GraphQL for its APIs. This mini-series will cover the steps needed to set up your own production-ready GraphQL server in AWS, using the Serverless Framework, Node.js, and ApolloServer. It utilizes Lambda for running the server code, API Gateway to serve our GraphQL API, and DynamoDB as our backing data store.

Create the Service

To get started, you’ll want to make sure you have an AWS account set up and configured for Serverless.

Next, we’ll want to generate our service using one of the templates. Run the following commands in your terminal, replacing my-graphql-service with the name of your service:

mkdir -p ~/my-graphql-service
cd ~/my-graphql-service
npx serverless create --template aws-nodejs-ecma-script -n my-graphql-service
yarn install

Using a template ensures we are using the latest standards; however, it requires some cleanup:

  • Add a locked version of serverless: yarn add -D serverless
  • Delete example handlers: rm first.js second.js
  • In the serverless.yml file, delete everything under functions

Next, we’ll want to add some better default options to our service. In the serverless.yml we’ll want to add the following under the provider field:

# Generated code...
minimumCompressionSize: 1024 # Enable gzip compression for responses > 1 KB
SERVICE: ${self:service}
STAGE: ${opt:stage}
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1 # Use http keep-alive for AWS connections

Let's add the GraphQL and ApolloServer dependencies:

yarn add graphql apollo-server-lambda graphql-tag graphql-tools

Create the GraphQL API

Create the GraphQL and schema index.js files:

mkdir -p src/graphQl/schema && touch src/graphQl/index.js && touch src/graphQl/schema/index.js

Since we’re just setting up the server, we’ll create a temporary GraphQL schema for testing purposes. Add the following to your schema index file:

Now we can set up our GraphQL handler code. Update your GraphQL index file:

You’ll notice we have enabled introspection when not using a prod stage. If developing a public API, you should always enable it so that your API consumers can view the documentation.

Add the GraphQL function to your serverless.yml file under the functions field:

handler: src/graphQL/index.graphQlHandler
- http:
path: /graphql
method: post
cors: true

Now we have a functioning GraphQL service that can be deployed! You can test out a dev deployment by running:

yarn serverless deploy -s dev

Setup GraphQL Playground

Manually invoking a GraphQL API is cumbersome, so we’re going to set up a GraphQL Playground environment to make manual testing of our API much easier.

Install the GraphQL Playground dependencies:

yarn add graphql-playground-middleware-lambda aws-lambda

Add the playground handler to your GraphQL index file:

import lambdaPlayground from 'graphql-playground-middleware-lambda';export const playgroundHandler = lambdaPlayground({
endpoint: `/${process.env.STAGE}/graphql`,

Now add the playground function to your serverless.yml file:

# Existing graphQl function

handler: src/graphQL/index.playgroundHandler
- http:
path: /playground
method: get
cors: true

You may consider securing your playground API unless your API is public

Now let's deploy our service so we can use the playground:

yarn serverless deploy -s dev

You should see the deployment result like so:

Grab the playground endpoint and paste it into your browser. It should load up the playground and allow you to view our temporary schema and query the ping field.

Extra Credit: Unit Tests

We will be using Jest for our testing framework. Add the dependencies and initialize the project:

yarn add -D jest babel-jest @babel/core @babel/preset-env
yarn jest --init

Create a babel.config.js file in the root of your project:

Now you can create some unit tests.

Follow the JetClosing Engineering Blog and stay tuned for the next part which will include creating the API data with corresponding GraphQL schema and resolvers. Check out the example repo for an implementation of everything up to this point.




Engineering and technology articles by JetClosing engineers

Recommended from Medium

Modern Django — Part 1: Project Refactor and Meeting the Django Settings API

Can Kafka be used for video streaming?

Good (& Free) Calendar for Windows

Part of a keyboard, a pad and pencil, and a calendar app on a tablet

Structuring Multipart FormData with Rails Naming Conventions

Oxygen Builder Review — The Good, The Bad, and The Competition

How to Get Started With the Neo4j Graph Data Science Python Client

Demystifying how your browser handles a request

Why does C KingDom choose to launch on Binance Smart Chain(BSC)?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Chris Feist

Chris Feist

Full stack developer specializing in React and React Native front ends, and AWS backends

More from Medium

Getting Started With Serverless Framework

Accelerating AWS deployment when using Typescript

Frictionless Serverless Development: Part 3— Authentication

Creating Tables with DynamoDB Toolbox