🧙 Lambdalith Mastery: Elevating NestJS Deployment on AWS Lambda with CDK & Webpack
Tags: serverless, aws, javascript, tutorial
Published: 2023-11-16 14:45:29

---
published: true
title: '🧙 Lambdalith Mastery: Elevating NestJS Deployment on AWS Lambda with CDK & Webpack'
description: 'Learn how to deploy a monolithic NestJS app on AWS Lambda using Webpack and AWS CDK.'
series:
canonical_url:
cover_image: 'https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju2aagya3m56n0xx36l0.png'
tags: serverless, aws, javascript, tutorial
---

## TL;DR 📚
- Why is a Lambdalith approach a high ROI choice for many? 💸
- Learn how to deploy a monolithic NestJS app on AWS Lambda using Webpack and AWS CDK. 🚀

## The Lambdalith Edge for NestJS on AWS Lambda 🌟
>🧠 A Lambdalith is a monolithic architecture approach for serverless applications where a single AWS Lambda function serves the entire API, rather than deploying separate functions for each endpoint.

Opt for a Lambdalith and reap multiple benefits for your NestJS API:

- **Faster Rollouts**: Quicker deployments and streamlined management, irrespective of your number of routes.
- **Minimized Cold Starts**: Enhanced performance through more frequent reuse of a single Lambda function.
- **Easier Logging**: A single point for logs simplifies monitoring and alert setup.
- **Full NestJS Benefits**: Fully exploit NestJS's rich features and community support.

While a Lambdalith might mean lengthier cold starts and broader control scopes, its efficiency, simplicity, and high return on investment are unmatched.

>**Monorepo structure 🚧📦:** I strongly advice you embrace a monorepo structure, with a package for your API and a package for your infrastructure (CDK).

## Setting Up the Infrastructure with AWS CDK 🏗️
AWS CDK transforms infrastructure into code. Kick things off by installing AWS CDK and initiating a TypeScript project with `cdk init app --language typescript`.

In the `lib/my-stack.ts` file, begin with the core of your setup: the Lambda function.

```typescript
// LambdaNestStack in stack.ts
const apiNestHandlerFunction = new Function(this, "ApiNestHandler", {
  code: Code.fromAsset("api/dist"), // 👈 This is crucial
  runtime: Runtime.NODEJS_18_X,
  handler: "main.handler",
  environment: {}, // 👈 You might need env variables
});
```
Next up, create a Rest API with a Lambda proxy at its root. This API Gateway acts as the traffic controller, directing all requests to your Lambda-powered NestJS app. All route paths will be directed to your single Lambda. 🗾

```typescript
const api = new RestApi(this, "Api", {
	deploy: true,
	defaultMethodOptions: {
	apiKeyRequired: true,
	},
});

api.root.addProxy({
	defaultIntegration: new LambdaIntegration(apiNestHandlerFunction, { proxy: true }),
});

const apiKey = api.addApiKey("ApiKey"); // 👈 to ease your testing

const usagePlan = api.addUsagePlan("UsagePlan", {
	name: "UsagePlan",
	apiStages: [
	{
		api,
		stage: api.deploymentStage,
	},
	],
});

usagePlan.addApiKey(apiKey);
```

In this snippet, `Code.fromAsset("api/dist")` is crucial. It points to the location of our bundled NestJS app, ensuring efficient Lambda execution.

## Prepping the NestJS App for Lambda 🦁

Start by creating a new NestJS app with `nest new api`. Then, install the `@nestjs/platform-express` and `@vendia/serverless-express` packages.
You now have a classic NestJS app, ready to be adapted for AWS Lambda.

Next to the `main.ts` file, create a new `lambda.ts` file. This file will be the entry point of our Lambda function.

```typescript
// lambda.ts
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import serverlessExpress from '@vendia/serverless-express';
import { Context, Handler } from 'aws-lambda';
import express from 'express';

import { AppModule } from './app.module';

let cachedServer: Handler;

async function bootstrap() {
  if (!cachedServer) {
    const expressApp = express();
    const nestApp = await NestFactory.create(
      AppModule,
      new ExpressAdapter(expressApp),
    );

    nestApp.enableCors();

    await nestApp.init();

    cachedServer = serverlessExpress({ app: expressApp });
  }

  return cachedServer;
}

const handler = async (event: any, context: Context, callback: any) => {
  const server = await bootstrap();
  return server(event, context, callback);
};

module.exports.handler = handler;
```

This code will be executed by AWS Lambda. It creates a NestJS app and adapts it to the AWS Lambda environment. It also ensures that the NestJS app is only created once, improving performance. ⚡

>**🗒️ Side Note**: You could easily setup a single `main.ts` entry point by leveraging env variables to deduce the execution context: Lambda or local

Now, we need to bundle this TypeScript code into a single file...🤓

## Packing it Up with Webpack 📦🧙‍♂️
There are several ways to bundle a NestJS app for AWS Lambda. You could use Lambda Layers, but this is not the most efficient approach. Instead, we'll use Webpack to bundle our NestJS app into a single file, which we'll then deploy with AWS CDK.

Let's start by creating a new `webpack.config.js` file in our API package. This file will define our Webpack configuration.

```javascript
module.exports = function (options, webpack) {
  return {
    ...options,
    entry: ['./src/lambda.ts'],
    externals: [],
    output: {
      ...options.output,
      libraryTarget: 'commonjs2',
    },
    plugins: [
      ...options.plugins,
      new webpack.IgnorePlugin({
        checkResource(resource) {
          // Ignoring non-essential modules for Lambda deployment
          return lazyImports.includes(resource);
        },
      }),
    ],
  };
};
```
This configuration bundles our Lambda entry file (`lambda.ts`) and its dependencies, creating a lean and efficient package for AWS Lambda!

Make sure to create a build-lambda script in your `package.json` file!

```json
{
  "scripts": {
	"build-lambda": "nest build --webpack --webpackPath webpack.config.js"
  }
}
```

## Deploying the NestJS App: To the Cloud! ☁️
Your NestJS app is now a compact bundle, thanks to Webpack. Deploying? It's as simple as:

- **Build**: Run `npm run build-lambda` in your API package.
- **Deploy**: In your infrastructure package, execute `cdk deploy`.

And like that, your NestJS app ascends to AWS Lambda, primed for action. 💫

## Your High-Performance NestJS App now lives on AWS 🚀

Congratulations! You've unlocked the strategy for a potent, scalable, and efficient NestJS app on AWS Lambda, all packaged neatly with Webpack and AWS CDK. 👏👏

Please feel free to comment if anything was unclear or if you found a better way to achieve this result! 💬