Before reading this article, I recommend reading the one about the Serverless platform and simple deployment of the Next.js app with Serverless.

Our goal?

Our main goal is to deploy GraphQL backend with Fastify framework to AWS Lambda using Serverless framework.

Fastify

Fastify is a web framework highly focused on providing the best developer experience with minor overhead and a robust plugin architecture. It is inspired by Hapi and Express and is one of the fastest web frameworks.

Core features are:

  • Highly performant

  • Extendible

  • Schema-based

  • Logging

  • Developer friendly

Getting started with Fastify is easy. Just create an empty folder, and inside it generate a fastify project:

1npm init fastify

and after that, install dependencies:

1npm install

You can then start the app in dev mode using npm run dev, but that is not where we want to stop now.  

Also, if you have an existing project, you can install Fastify as a dependency:

1npm i fastify --save

Fastify-gql

The next step is installing fastify-gql, which gives us the best of two dependencies: Fast and efficient server and easy and optimal query support from GraphQL:

1npm i fastify fastify-gql

*this command covers both the first step and the fastify-gql step

We will use the following example and write down in our app.js the following code:

1'use strict'
2
3const Fastify = require('fastify')
4const GQL = require('fastify-gql')
5
6const app = Fastify()
7
8const schema = `
9  type Query {
10    add(x: Int, y: Int): Int
11  }
12`
13
14const resolvers = {
15  Query: {
16    add: async (_, { x, y }) => x + y
17  }
18}
19
20app.register(GQL, {
21  schema,
22  resolvers
23})
24
25app.get('/', async function (req, reply) {
26  const query = '{ add(x: 2, y: 2) }'
27  return reply.graphql(query)
28})
29
30app.listen(3000)

Our code can now run on localhost:3000 by running it from the terminal using:

1node app.js

AWS-Lambda-Fastify

Using AWS services with Fasitfy is also a great combo and boost to your server response.

Add this feature using:

1npm install aws-lambda-fastify

Now we need to create a new lambda.js file in our root folder, which looks like this:

1const awsLambdaFastify = require('aws-lambda-fastify')
2const app = require('./app')
3
4const proxy = awsLambdaFastify(app)
5// or
6// const proxy = awsLambdaFastify(app, { binaryMimeTypes: ['application/octet-stream'] })
7
8exports.handler = proxy
9// or
10// exports.handler = (event, context, callback) => proxy(event, context, callback)
11// or
12// exports.handler = (event, context) => proxy(event, context)
13// or
14// exports.handler = async (event, context) => proxy(event, context)

And add a little tweak to your app.js file by removing the last line of code and replace it with this:

1if (require.main === module) {
2  // called directly i.e. "node app"
3  app.listen(3000, (err) => {
4    if (err) console.error(err)
5    console.log('server listening on 3000')
6  })
7} else {
8  // required as a module => executed on aws lambda
9  module.exports = app
10}

When executed in your lambda function, we don't need to listen to a specific port, so we export the app.js in this case. The lambda.js file will use this export. You can now rerun the app using the same command node app.js.

Serverless GraphQL endpoint

Now that we covered the basics about using Fasitfy combined with GraphQL and AWS, we can get back to our Serverless deployment, which includes configuring our serverless.yml, which was mentioned in the previous article:

1#serverless.yml
2
3functions:
4  graphql:
5    handler: handler.graphqlHandler
6    events:
7    - http:
8        path: graphql
9        method: post
10        cors: true

Any HTTP POST event on the path /graphql will trigger the graphql Lambda function and will be handled by graphqlHandler.

The rest of the configuration is just creating a GraphQL schema, Lambda function with your needs, and you are ready to go!

In sum, powering your GraphQL endpoint with a Serverless backend solves scaling and availability concerns outright, and it gives you a big leg up on security. It’s not even that much code or configuration!