NestJS Fastify — AWS Lambda

Muthu Venkatachalam
The Nobody’s of Tech
5 min readJan 6, 2021

What is NestJS?

NestJS is a Node.js framework for developing server-side application. I for one developed a liking towards NestJS as it is simple, self-contained and a popular library for developing synchronous REST apis and Microservices.

Why NestJS on AWS Lambda? (Controversy Alert!)

The cloud community is very divided in terms of using a framework like express, fastify or springboot as opposed to using functions. By now you know I’m on the framework side. I believe as long as you could keep the size of the lambda, latency and use other best practices in terms of connecting to AWS services like dynamodb, etc. Two major reasons for going the framework:

  • Sticking to regular Microservices pattern & leverage serverless too
  • Only for Synchronous APIs involving REST (don’t recommend for async)

Which NestJS Platform?

NestJS offers two platforms — express or fastify. I have developed and deployed nestjs-express applications in prod and its a decently performing application, not blazingly fast but gets the job done. There are several good articles for deploying nestjs-express application in AWS-Lambda, I found this one particularly helpful when I got started —medium-post

Now that I’m comfortable and I have a proven use case with Nestjs Express, I want to take 1 level up and try the fastify platform on lambda. Fastify has benchmarked the performance and yes it is fast (no surprise!). So lets now refine our use case to NestJSPlatform-Fastify

Getting Started

NestJs has a cli that takes care of creating a starter project for us. I create a new project and update the package.json to the latest nestjs component versions and the platform-fastify dependency.

main.ts for fastify

Also add ‘aws-lambda’ (sdk) as dev dependency

npm i -D aws-lambda
# build the project
npm install
# start local
npm run start:dev

Now the local endpoint should be available at localhost:3000

Lets Plugin Lambda

Shout out to Fastify, they offer aws-lambda-fastify which is similar to the serverless-express and they get us covered. Only part left is for us to include the NestJS wrapper on top of it, lets do that! Below lambda.ts supports latest version of NestJS fastify & also on Fastify v3

Optimize the package

When deploying to lambda, we should make the package as lightweight as possible so that we beat cold-start as much as we can. I’m not using serverless or SAM, so am keeping this use-case as simple as possible so that it can be leveraged across the CI you use in your team (I use Gitlab CI with a custom deployment script similar to lambda-python)

TSConfig — It is important to include only dist files and exclude other source files, so i add this setting in my tsconfig

#compiler-options
"outDir": "./dist"
"rootDir": "src"
# Exclusions
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]

Now running ‘tsc’ should generate the dist directory with the trans-piled js files & mapping

Now lets concentrate on the node_modules and how we can reduce the package size. While browserify & minify are advocated as means to recduce the package size, it doesn’t work out for all and sometimes has the potential to break the runtime if not configured properly. So am keeping things simple here as well and taking some best practices from couple of good sources: https://tsh.io/blog/reduce-node-modules-for-better-performance/ and improvise on top of it for nestjs and lambda

Install https://github.com/tj/node-prune, this is different from the node-prune (npm package), I got confused too initially. In your CI or wherever you build the production package install is using below command

curl -sf https://gobinaries.com/tj/node-prune | sh

Then I run the following npm scripts to downsize the node_modules

"install:prod": "rm -rf node_modules && rm -rf package-lock.json && npm install --production --no-package-lock","prune_me": "npm prune --production && node-prune && rimraf node_modules/rxjs/src && rimraf node_modules/rxjs/bundles && rimraf node_modules/rxjs/_esm*"npm run install:prod && npm run prune_me

rxjs is a pretty heavy module which you need to target & if you start expanding more on nestjs, you might need class-validator you can remove esm package from there too. Believe it or not the final package size went down to 1.9MB after all this pruning. Definitely if you add more libraries it is going to increase, but be mindful of what you add to your dependency. For instance keep ‘aws-lambda’ sdk, all typings and use your own utilities than adding a wholesome library like lodash (refer — https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore)

Deploy the Package

Zip both the dist & node_modules folder and upload the zip file to lambda

Lets add the API-Gateway test event to the lambda. The Test should yield the sample ‘Hello World’ response in api-gateway response format

I have not benchmarked the performance in the aws-lambda but fastify has done this for us here and is definitely better than nestjs-express

Github Project

Conclusion

If you are someone who has developed microservices with frameworks like nestjs, express, spring boot, etc. and now equally excited by serverless developments, you are not alone. While nano services (single purpose functions) are preferred by majority in the community for serverless functions, it’s not the de-facto. Also if that were the case you also wouldn’t see much traction for libraries that enable using these frameworks with serverless gain popularity by the day. I like the word “Opinionated” once I got to know microservices, just use it wisely ☺️

Further Reading

For a production grade application, we will need more components

--

--