Deploy a Fastify app on Lambda (A serverless application)

More from Author
Akash

Engineering Lead

Tags:
AWS - Lambda
10 min read

Before we go into details, let us first discuss what is fastify and what is serverless.

What is Fastify?

Fastify is a fast and low-overhead web framework for Node.js
Reference: www.fastify.io

Why use Fastify?

An efficient server implies a lower cost of the infrastructure, better responsiveness under load, and happy users. How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests possible, without sacrificing security validations and handy development?

Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and powerful plugin architecture, inspired by Hapi and Express. As far as we know, it is one of the fastest web frameworks in town.

Who is using Fastify?

Fastify is proudly powering a large ecosystem of organizations and products out there. Some of the famous companies using Fastify are:

What is serverless?

Serverless is an architecture for deploying code without maintaining a server. It only runs as needed, and the cloud provider handles most “ops” related tasks.

AWS's serverless cloud service is called Lambda, and we tend to reach for it quite a bit. Lambda is not inherently HTTP based; it exposes its own interface for invoking its “functions'' (blocks of serverless code). So we use a library called serverless-http to adapt our functions into REST APIs, which any clients may consume.

Finally, the wonderful Serverless Framework handles the nitty-gritty of launching our code. It orchestrates ALL the cloud services in play; S3 for pushing code, API Gateway for handling HTTP requests, and of course Lambdas. But you don't have to worry about any of that- the tool takes care of these things behind the scenes.

Fastify Application

Let's build the app. Fast.
To get up and running, we will install fastify-cli and then generate the application.

1. To install fastify-cli use the command

Copy Code
    
 npm i fastify-cli --global
    
    

2. To create a project template use the command:

Copy Code
            
 fastify generate --lang=js fastify-lambda
            
        

-lang can be js or ts.

3. Install the dependencies

Copy Code
              
 cd fastify-lambda
 npm init 
              
          

Let us understand the default code.

The app.js in the root folder contains the following code

Copy Code
        
 'use strict'

 const path = require('path')
 const AutoLoad = require('@fastify/autoload')

 const app = async function (fastify, opts) {
 // This loads all plugins defined in plugins
 // those should be support plugins that are reused
 // through your application
 fastify.register(AutoLoad, {
     dir: path.join(__dirname, 'plugins'),
     options: Object.assign({}, opts)
 })

 // This loads all plugins defined in routes
 // define your routes in one of these
 fastify.register(AutoLoad, {
     dir: path.join(__dirname, 'routes'),
     options: Object.assign({}, opts)
 })
 }
 module.exports = app
        
      

This creates a default fastify app. Fastify.register is used to install a plugin.
Register the routes to the application by calling the function fastify.register with "routes" as a parameter.

Note: While in ExpressJS almost everything is a middleware in Fastify everything is a plugin

The default code in the file routes/root.js is as follows

Copy Code
        
 module.exports = async function (fastify, opts) {
     fastify.get('/', async function (request, reply) {
     return { root: true }
     })
 }
        
      

This creates a default route and returns a JSON response { root : “true” }

To check the response on local dev environment use the command

Copy Code
        
 npm run dev //starts the local dev environment
        
      

Add Custom Routes

Step 1 : Add default data

To keep the first project as simple as possible, let's avoid adding a database.
To replicate a database, let's create an items.js file and add some dummy data.

Copy Code
            
 let items = [
 {id: '1', tasks: "Eat"},
 {id: '2', tasks: "Code"},
 {id: '3', tasks: "Sleep"},
 {id: '4', tasks: "Repeat"}
 ]
            
        

Step 2 : Create a controller file

1. Create a new folder controller to save all the controller file.
2. Create a ItemController.js file to add the controller code.

Copy Code
            
 // get all the data from dummy database - items.js
 let items = require('../items')



 // Get all the items and send as response (reply)
 const getItems = async (req, reply) => { 
     reply.send(items)
 }



 // Get individual item by id and send as response (reply)
 const getItem = async (req, reply) => {
     const { id } = req.params
 
     const item = items.find((item) => item.id === id)

     reply.send(item)
 }

 module.exports = {
     getItems,
     getItem,
 }
            
        

Step 3 : Create routes and attach the controller to each route.

Modify the routes/root.js as follows

Copy Code
            
 'use strict'

 //Import the controller functions
 const {
 getItems,
 getItem,
 } = require('../controllers/ItemController')

 // Schema for the generic data - each item has 2 fields - id and tasks. 
 // id and tasks will be of type string
 const Item = {
 type: 'object',
         properties: {
             id: {type: 'string'},
             tasks: {type: 'string'},
         }
 }

 // Schema for get all response 
 const getItemsOpts = {
 schema: {
     response: {
     200: {
         type: 'array',
         items: Item
     }
     }
 },
 handler : getItems
 }

 // Schema for get unique item response
 const getItemOpts = {
 schema: {
     response: {
         200: Item
     }
 },
 handler: getItem
 }

 module.exports = async function (fastify, opts) {
 fastify.get('/', async function (request, reply) {
     return { root: true }
 })

 fastify.get('/items', getItemsOpts)
 fastify.get('/items/:id', getItemOpts)
 }
            
        

Let us create 2 routes -

  • To fetch all the tasks
  • To fetch a task by its id
Copy Code
          
 fastify.get('/items', getItemsOpts)
 fastify.get('/items/:id', getItemOpts)
          
        

Each route is has a handler function or options as per Fastify ( or in general terms views in MVC )
Example getItemsOpts and getItemOtps

Copy Code
        
 const getItemsOpts = {
     schema: {
     response: {
         200: {
         type: 'array',
         items: Item
         }
     }
     },
     handler : getItems
 }              
        
      

In the above code snippet, getItemsOpts option is defining a schema for the response. The Response contains an array of items and success status. And each element of array is an object of type Item [ schema ]

Copy Code
        
 const Item = {
     type: 'object',
             properties: {
                 id: {type: 'string'},
                 tasks: {type: 'string'},
             }
 }                            
        
      

To check the response on local dev environment use the command

Copy Code
        
 npm run dev //starts the local dev environment
        
      

127.0.0.1:3000/items will return the output

[{"id":"1","tasks":"Eat"},{"id":"2","tasks":"Code"},{"id":"3","tasks":"Sleep"},{"id":"4","tasks":"Repeat"}]

The AWS Serverless Application Model

The AWS Serverless Application Model (SAM) is an open-source framework for building serverless applications. It allows you to write a small YAML file to describe the function and the endpoints. And also with a simple command, the application is deployed to AWS Lambda and configured all the setup provisioning.

Basic SAM commands:

  • sam build
  • sam deploy to deploy the app to cloud
  • sam validate to check the configuration file
  • sam delete to delete the app from Lambda

Tools of Trade

Before digging into the world of serverless, let us first install the requisite software.

  • Create or login to AWS account.
  • Install AWS CLI
  • Install AWS SAM
  • Create an IAM user with Admin permissions (for practice)
  • Configure AWS CLI using the command.
  • Install Node, VS code (or any other IDE)
Copy Code
        
 aws configure
 AWS Access Key ID [None]: accesskey
 AWS Secret Access Key [None]: secretkey
 Default region name [None]: ap-south-1
 Default output format [None]:
        
      

Steps to deploy the fastify app onto a lambda service

Step 1: Create a template.yaml and add the following code

Copy Code
        
 AWSTemplateFormatVersion: "2010-09-09"
 Transform: AWS::Serverless-2016-10-31
 Description: >
 FastifyApp
 Sample SAM Template for app

 # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
 Globals:
 Function:
 Timeout: 3

 Resources:
 FastifyApp:
 Type: AWS::Serverless::Function
 Properties:
 Handler: dist/lambda.handler
 PackageType: Zip
 Runtime: nodejs14.x
 MemorySize: 128
 Timeout: 500
 Events:
     AppEventAPI:
     Type: HttpApi
     Properties:
         Path: /{proxy+}
         Method: any

 Outputs:
 # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
 # Find out more about other implicit resources you can reference within SAM
 # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
 AppEventAPI:
 Description: "API Gateway endpoint URL for Prod stage for Hello World function"
 Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/"
 FastifyApp:
 Description: "Hello World Lambda Function ARN"
 Value: !GetAtt FastifyApp.Arn
 FastifyAppIamRole:
 Description: "Implicit IAM Role created for Hello World function"
 Value: !GetAtt FastifyAppRole.Arn
        
      

The above file is a config file for the CloudFormation service. This will create a project in CloudFormaton with a Lambda function, and API gateway trigger attached to it.

Convert the app to Lambda

To get the events and all the data from AWS Gateway in our app we need an extra layer. Luckily we don't have to write it from scratch because there is a library available for this purpose. It's called aws-lambda-fastify. Let's install it and use it.

Copy Code
        
 npm i aws-lambda-fastify
        
      

Now we need to wrap our app with the library.

Create a lambda.js file in the root directory and add the following code.

Copy Code
        
 const awsLambdaFastify = require("aws-lambda-fastify");
 import "./app.js";

 const server = fastify({logger: true})


 const proxy = awsLambdaFastify(server);
 exports.handler = proxy;            
        
      

Congratulations we made it. Now, all we have to do is build the app and deploy it using the SAM CLI:

Copy Code
        
 sam build
 sam deploy 
        
      

To hire fastify developers, contact us at contact@bluetickconsultants.com or call us at +91-9004090513

Back To Blogs


Find out our capabilities to match your requirements

contact us