Serverless NestJS for Web Services

In the modern era of cloud computing, serverless architectures have gained immense popularity due to their scalability, cost-effectiveness, and ease of management. Stakeholders and developers are interested in deploying their applications using serverless computing because of its numerous advantages, which we will explore further in this article. This article will focus on the development web services using NestJS on AWS Lambda, one of the leading serverless computing platforms.

Choosing a Stack

Serverless computing doesn't mean that there is no server involved. Instead, it means that a cloud provider allocates machine resources on demand, taking care of the servers on behalf of their customers. This solution has its disadvantages - one of which is the cold start.

The cold start occurs the first time your code is executed after a period of inactivity. This process adds latency, which depends on several factors including the stack you are using, the programming language, the number of packages, and the number of modules to maintain.

Choosing the right stack is crucial to mitigating some of the inherent drawbacks of serverless architectures, such as cold starts. NestJS, combined with TypeScript, presents a compelling choice for several reasons:

  • Modular Architecture: NestJS follows a modular architecture, allowing for organized and maintainable code.
  • Developer Productivity: NestJS is one of the best frameworks for backend development in Node.js, thanks to its numerous modern features. TypeScript reduces the number of bugs by catching errors at the compile-time level.
  • Performance Optimization: NestJS is built on top of Express (or optionally, Fastify), both of which are lightweight and fast.
  • Community and Ecosystem: Both NestJS and TypeScript have large, active communities and a wealth of plugins and tools.
  • Seamless Integration with AWS Lambda: NestJS can be easily configured to run on AWS Lambda, leveraging the power of serverless computing while maintaining the framework’s architectural benefits.

Build and deployment

Serverless architecture should focus purely on individual functions in your application code. Let’s dive a little bit into creating a pure AWS Lambda function without the NestJS stack.

First, we need to navigate to the Lambda page on AWS and create a function. For the initial setup, we will choose Node.js because we are using the JavaScript language, and we'll use the standard x86 architecture.

This Lambda function, when invoked, will respond with an HTTP status code of 200 and a JSON body containing the string 'Hello From Koia'. This is a simple example demonstrating how to construct and return a basic response from an AWS Lambda function. Let’s try running some basic tests.

Each invocation of the Lambda function returns information about the duration of running the function and how much of that time is billable. Let’s stop here for a moment and talk about costs.

Users are billed primarily for Lambda execution time, but this is only part of the story. While there is no cost when it’s on standby, the costs are influenced by multiple factors. These include the execution time calculated based on GB-seconds (where GB refers to the cache memory allocated for the function execution), disk space, and the chosen architecture.

As a wise man once said: "With great power comes great responsibility," which applies to running Lambda functions. Serverless is essentially a server that scales automatically, meaning it could scale infinitely.

You can read more about potential costs on AWS Lambda pricing page.

Running Lambda using NestJs and serverless framework

Lambda functions are not always standalone functions; they often need to interact with other services. AWS Lambda can be used in various scenarios, such as hosting web services via Amazon API Gateway, executing custom logic within or outside of infrastructure, handling events (e.g., generating thumbnails), and general automation tasks using the AWS SDK.

While the best solution might be a tailor-made system, there are ready-made packages that help build and deploy serverless applications without the need to create custom build and deployment pipelines. One such package is the Serverless Framework, which is fully supported by NestJS documentation.

This tool allows us not only to deploy the Lambda with API Gateway configuration but also to run Lambda locally for development purposes. Let’s create a handler for the Lambda.

We also have to create a serverless.yml file to configure the Serverless framework:

And there you go, you have created a skeleton for a NestJS app using the Serverless framework. You have to provide AWS credentials so that Serverless has permission to create AWS Lambda, S3 bucket, and IAM user.

Practical use case

We know what a lambda is and how to create one in NestJs, but let’s try to implement functionality and see how it behaves.

Consider a situation where our application needs to store files in an AWS S3 bucket, and we want our backend to save these files. Although Node.js is asynchronous and can handle many I/O-bound tasks efficiently, uploading large files can still be challenging. While Node.js uses an event-driven, non-blocking I/O model, leveraging AWS Lambda can provide additional benefits. Using AWS Lambda for handling file uploads is advantageous because it can offload the intensive task of uploading large files from our monolith service.

Prerequisites:

  1. Serverless Framework: Install the Serverless Framework globally using npm: npm install -g serverless
  2. AWS Credentials: Configure your AWS credentials to allow the Serverless Framework to deploy to your AWS account. Follow the AWS CLI configuration guide.

You can find all dependencies in this repository

First, we have to create a module with a controller in our NestJs application:

The next step would be to save the file through the service:

Remember to save your new module to imports array in your AppModule

We also need to provide environment variables to our serverless.yml file

Let’s try running our app with an npx serverless offline command.

The Serverless-offline plugin mimics how AWS Lambda behaves in the cloud. Currently, it’s on standby, so we are not incurring any costs. Let’s try uploading a file through our code.

You can see that the response is 201 Created, which means that the lambda executed our code successfully.

You can also see an interesting thing in our local logs: I sent two very similar requests with a timestamp 2 seconds apart. The billed duration for the first request is almost twice as long as the second request due to a cold start.

Deployment on AWS

We have successfully created a working NestJs with lambda application locally, but it’s only valuable if others can use it, right?

Authentication guards should protect your controller so that your Lambda function is not exposed to unauthorized requests. This article will not focus on that but remember the risks of deploying your app without protection.

We provided credentials via config files since we were running our app locally and our S3 bucket was not public. Now, we have to give permissions for our application.

To build and deploy the application, use the following commands:npm run build && sls deploy

We have successfully deployed our lambda on AWS! Let’s go to AWS CloudFormation, API Gateway and confirm that.

Now let’s try to send first request, we can see the response in CloudWatch

We can now confirm that we have fully deployed the lambda on AWS!

Conclusion

Serverless computing can be an excellent and cost-effective option for applications that are not frequently used or are used periodically. By leveraging AWS Lambda and frameworks like NestJS with the Serverless Framework, developers can create scalable, maintainable, and efficient applications. Additionally, serverless computing can serve as an extension of existing applications, providing a suitable solution for specific use cases where a different tech stack is more advantageous. However, careful consideration must be given to stack selection and the inherent challenges of serverless architectures, such as potential infinite scaling.

Author : Marek Kluk

“Full stack JavaScript developer with a strong passion for backend. My main technologies are NestJS and React, with a touch of AWS. Privately, my interests include kickboxing, squash, and hiking with my dog, Yogi.”

Contact

What can we do together?

Give us a brief introduction of your current situation and our client
team will take care of your needs.
Thanks for Reaching Out!

We've got your message and our team will be in touch soon. Looking forward to connecting!
Oops! Something went wrong while submitting the form.