---
title: 'Deploy Nest JS on AWS'
description: 'Deploy a Nest JS application on AWS Lambda and API Gateway using AWS CDK.'
---
import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components';
Deploy your [Nest JS](https://nestjs.com/) app on AWS with Lambda and API Gateway using the [AWS CDK](https://aws.amazon.com/cdk/).
There are a few ways to deploy your Nest JS app on AWS:
1. Standard Lambda and API Gateway.
2. Node.js runtime container image on Lambda.
3. Bun runtime container image on Lambda.
4. One-click installation on your AWS account using [Thunder console](https://console.thunder.so).
View example code
## Deploy Nest JS on AWS Lambda + API Gateway
---
[CDK Functions](https://github.com/thunder-so/cdk-functions) is a package that simplifies the deployment of Lambdas using the AWS Cloud Development Kit (CDK). It provides a straightforward way to deploy your Nest JS app to AWS Lambda and API Gateway.
### 1. Create a project
You can create a new Nest JS project using the following commands:
```sh
npm create nestjs@latest my-nestjs-app
cd my-nestjs-app
```
```sh
pnpm create nestjs my-nestjs-app
cd my-nestjs-app
```
```sh
bun create nestjs my-nestjs-app
cd my-nestjs-app
```
### 2. Initialize your project
Install the necessary dependencies and initialize your project:
```sh
npm i tsx aws-cdk-lib @thunderso/cdk-functions --save-dev
```
```sh
pnpm add -D tsx aws-cdk-lib @thunderso/cdk-functions
```
```sh
bun add -d tsx aws-cdk-lib @thunderso/cdk-functions
```
### 3. Create a CDK stack and Lambda handler
Create a `stack/index.ts` file to create your CDK stack. Edit it to match your project:
```ts
// stack/index.ts
import { App } from "aws-cdk-lib";
import { Runtime, Architecture} from 'aws-cdk-lib/aws-lambda';
import { FunctionStack, type FunctionProps } from '@thunder-so/cdk-functions';
const fnStack: FunctionProps = {
env: {
account: '4477996600XX',
region: 'us-east-1',
},
application: 'nestjs',
service: 'api',
environment: 'dev',
functionProps: {
codeDir: 'dist',
handler: 'lambda-node.handler',
include: [
'node_modules', // Include node_modules for dependencies
'lambda-node.js', // Include the Lambda handler file
],
exclude: ['node_modules/.npmignore', '**/*.ts', '**/*.map'],
},
};
new FunctionStack(new App(),
`${fnStack.application}-${fnStack.service}-${fnStack.environment}-stack`,
fnStack
);
```
Create a `lambda-node.js` file in the root directory to handle the Lambda function:
```ts
// src/lambda-node.js
const { NestFactory } = require('@nestjs/core');
const { AppModule } = require('./app.module');
const { configure } = require('@vendia/serverless-express');
let cachedServer;
async function bootstrapServer() {
if (!cachedServer) {
const app = await NestFactory.create(AppModule);
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
cachedServer = configure({ app: expressApp });
}
return cachedServer;
}
exports.handler = async (event, context) => {
const server = await bootstrapServer();
return server(event, context);
};
```
### 4. Deploy
Before you deploy, run your build script to generate artifacts in the `dist` directory.
```sh
npm run build
```
```sh
pnpm run build
```
```sh
bun run build
```
By running the following script, the CDK stack will be deployed to AWS.
```sh
npx cdk deploy --all --app="npx tsx stack/index.ts"
```
```sh
pnpm exec cdk deploy --all --app="pnpm exec tsx stack/index.ts"
```
```sh
npx cdk deploy --all --app="bunx tsx stack/index.ts"
```
When the deployment is complete, you will see the API Gateway URL in the output. You can access your Nest JS app at that URL.
For complete documentation, refer to the [CDK Functions documentation](https://github.com/thunderso/cdk-functions).
## Node.js runtime container image on Lambda
---
You can also deploy your Nest JS app on AWS Lambda using a Node.js container image. This method allows you to package your application and its dependencies into a Docker image, which can then be deployed to AWS Lambda.
### 1. Create a lambda handler
Create a `lambda-node.js` file in the root directory to handle the Lambda function:
```js
const { NestFactory } = require('@nestjs/core');
const { AppModule } = require('./app.module');
const { configure } = require('@vendia/serverless-express');
let cachedServer;
async function bootstrapServer() {
if (!cachedServer) {
const app = await NestFactory.create(AppModule);
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
cachedServer = configure({ app: expressApp });
}
return cachedServer;
}
exports.handler = async (event, context) => {
const server = await bootstrapServer();
return server(event, context);
};
```
### 2. Create a Dockerfile
Create a `Dockerfile.node` in the root directory to build your Nest JS app as a container image:
```dockerfile
FROM public.ecr.aws/lambda/nodejs:22 AS base
WORKDIR ${LAMBDA_TASK_ROOT}
# Copy dist files and install dependencies
COPY . .
RUN npm install --omit=dev
# Set the Lambda handler
CMD [ "lambda-node.handler" ]
```
### Create/modify your CDK stack
Create a `stack/node.ts` file (or modify your existing `stack/index.ts`) to define your CDK stack:
```ts
// stack/node.ts
const fnStack: FunctionProps = {
// ... other props
functionProps: {
codeDir: 'dist',
include: [
'package.json', // Include package.json for dependencies
'lambda-node.js' // Include the Lambda handler file
],
dockerFile: 'Dockerfile.node',
},
};
```
By running the following script, the CDK stack will be deployed to AWS.
```sh
npx cdk deploy --all --app="npx tsx stack/node.ts"
```
```sh
pnpm exec cdk deploy --all --app="pnpm exec tsx stack/node.ts"
```
```sh
npx cdk deploy --all --app="bunx tsx stack/node.ts"
```
## Bun runtime container image on Lambda
---
You can also deploy your Nest JS app on AWS Lambda with custom Bun runtime.
### 1. Create a lambda handler
Create a `lambda-bun.js` file in the root directory to handle the Lambda function:
```ts
// lambda-bun.js
const { NestFactory } = require('@nestjs/core');
const { AppModule } = require('./app.module');
let app, expressApp;
async function getExpressApp() {
if (!expressApp) {
app = await NestFactory.create(AppModule);
await app.init();
expressApp = app.getHttpAdapter().getInstance();
}
return expressApp;
}
exports.fetch = async (request /*: Request*/, server /*: Server*/) => {
const expressApp = await getExpressApp();
// Convert Bun's Request to Node.js req/res for Express
// Use 'node-fetch' Response to Express bridge
const { Readable } = require('stream');
const { Headers } = require('node-fetch');
// Create a mock req object
const url = new URL(request.url);
const req = new Readable();
req.url = url.pathname + url.search;
req.method = request.method;
req.headers = Object.fromEntries(request.headers.entries());
req._read = () => {};
if (request.body) {
const body = Buffer.from(await request.arrayBuffer());
req.push(body);
}
req.push(null);
// Create a mock res object
return new Promise((resolve) => {
const chunks = [];
const res = {
statusCode: 200,
headers: {},
setHeader(key, value) { this.headers[key] = value; },
getHeader(key) { return this.headers[key]; },
write(chunk) { chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); },
end(chunk) {
if (chunk) this.write(chunk);
const body = Buffer.concat(chunks);
resolve(
new Response(body, {
status: res.statusCode,
headers: res.headers,
})
);
},
status(code) { this.statusCode = code; return this; },
send(body) { this.end(body); },
};
expressApp(req, res);
});
};
```
### 2. Create a Dockerfile
Create a `Dockerfile.bun` in the root directory to build your Nest JS app as a container image with Bun runtime:
```dockerfile
# Builder image
FROM oven/bun:latest AS bun
WORKDIR /tmp
## Install the bun dependencies
RUN apt-get update && apt-get install -y curl
RUN curl -fsSL https://raw.githubusercontent.com/oven-sh/bun/main/packages/bun-lambda/runtime.ts -o /tmp/runtime.ts
RUN bun install aws4fetch
RUN bun build --compile runtime.ts --outfile bootstrap
# Runtime image
FROM public.ecr.aws/lambda/provided:al2023
WORKDIR ${LAMBDA_TASK_ROOT}
## Copy bun + bootstrap from the builder image
COPY --from=bun /usr/local/bin/bun /opt/bun
COPY --from=bun /tmp/bootstrap ${LAMBDA_RUNTIME_DIR}
## Copy dist files and install dependencies
COPY . .
RUN /opt/bun install --frozen-lockfile
# Set our handler method
CMD [ "lambda-bun.fetch" ]
```
### 3. Create/modify your CDK stack
Create a `stack/bun.ts` file to define your CDK stack:
```ts
// stack/bun.ts
const fnStack: FunctionProps = {
// ... other props
functionProps: {
codeDir: 'dist',
include: [
'package.json', // Include package.json for dependencies
'bun.lock', // Include bun.lock for Bun dependencies
'lambda-bun.js' // Include the Lambda handler file
],
dockerFile: 'Dockerfile.bun',
},
};
```
By running the following script, the CDK stack will be deployed to AWS.
```sh
npx cdk deploy --all --app="bunx tsx stack/bun.ts"
```