A NestJS microservice with Serverless Framework

My experience at Limehome using Serverless together with NestJS

Matthias Werndle
limehome-engineering
4 min readMay 12, 2020

--

What I do

I work as a full stack developer at Limehome. In the past few months I was involved in creating a Node.js API which is responsible for customer accounts together with NestJS and Serverless. In this article, I am going to share some opinions about those two frameworks from a developer’s perspective.

Why NestJS?

Most of you might be familiar with Express.js. A lightweight and simple Web-Framework, which gained popularity in the Node.js community during the last years. At Limehome we are using it for an internal Web-Application. Generally, we have a positive experience with it, however, problems started occurring when the application scaled up more. Parts like defining the OpenApi specification, writing unit tests and maintaining module dependencies got harder. Due to these reasons, we considered using a new Node.js framework when we started designing the new API for our customer accounts. Here comes NestJS into play: You can think of it like a wrapper for Express.js or Fastify. It handles most of the redundant parts of creating a Web-Application backend with the help of decorators and other abstraction classes.

TypeScript is supported by default. This enables you to generate OpenApi specifications by the same classes which are also responsible for the functionality. Due to the Angular like module system, dependency injection is completely painless. This will help to accelerate the speed of writing mocks for units tests.

Pros:

  • Detailed documentation with a lot of recipes for the integration of different libraries
  • Supports TypeScript by default, which helps to scale the project
  • Easy module and dependency injection system
  • A lot of abstraction classes to reduce redundant work

Cons:

  • For small projects the module system can lead to overhead
  • Moves away from the simplicity approach a lot Node.js libraries try to follow

Overall the usage of NestJS eliminated a lot of problems we encountered with our Express.js application and helped to speed up our development.

Why Serverless?

While planning of the new API, Alex Di Mango, our Head of Engineering, suggested trying the Serverless approach. The idea of Serverless is that the creation of instances from your application will be completely handled by a cloud provider depending on incoming requests. When an instance has not received a request within a certain time, it will be deleted.

In addition to that, there is a Framework called Serverless which helps to define the required configurations for different cloud providers. At Limehome we use Amazon Web Services Lambdas to handle our instances.

Pros

  • No need to handle or define any infrastructure for Node.js applications manually
  • Automatically scales up depending on the incoming work load
  • Payment price for cloud providers (for example Amazon Web Services) depends on the actual usage of instances, so we only pay for what is actually being used

Cons

  • If no instance is running, an incoming request will take longer (this is also called “cold start”)

How do they work together?

The list of pros and cons for both libraries can be of course extended. The points you can read in this article describe mostly on our experiences with them so far.

So what is the experience of the combination of those two libraries?

For the most parts they are completely independent from each other. You only need to provide the Serverless Framwork a JavaScript function that returns an object which is holding an Express.js instance.

Basic setup example

In the following, I will show a small example on how to setup both frameworks together. For this example, I use the following NPM modules:

In the upper code you can see, that we are calling a function createApp, applies the NestJS defined API specifications to the expressApp instance. This can be used by the Serverless Framwork and after some processing returned by handler.

Now we have to define how the Serverless Framework has to interact with AWS Lambda. Therefore, we specify a serverless.yml file:

This configuration file allows you to set everything AWS Lambda needs to know. For example:

  • Path of your handler function
  • Which runtime to choose
  • Which plugins should be used
  • Which networks the runtime has access to

You can also see that we stored a reference of a object of a secrects.yml file, depending on the stage of the provider. This file contains environment variables which can be applied to the runtime:

In our gitlab-ci.yml we then just simply run our Serverless framework configuration with different stages. Here you can find more information about deploying on AWS.

There are cases in which running Serverless makes a difference. For example, we encountered that NestJS has a relatively slow startup time compared to ExpressJS. This can lead to time intensive “cold starts” which will be noticed by the customer when he is waiting for a response. To solve this problem there is a plugin called Warmup which calls your instances in a specified interval, to keep them running.

In general both Framework are a perfect fit for modern Node.js development together. They both handle as much redundant work that developers do as possible. They also help us to fully concentrate on the implementation of required features for the customer.

--

--