Deploy NestJS on AWS

Deploy your NestJS applications to AWS using Thunder patterns. This guide covers both serverless Lambda deployment and containerized service options.

There are two deployment patterns available for NestJS on AWS:

  1. Lambda — Deploy NestJS API endpoints using AWS Lambda and API Gateway with the Lambda construct
  2. Containerized Service — Deploy containerized NestJS applications using ECS Fargate with the Fargate construct

Lambda Deployment


Deploy NestJS applications to AWS Lambda and API Gateway using the Lambda construct. This pattern is ideal for API endpoints, serverless functions, and event-driven architectures.

Create Project

Terminal window
npm create nestjs@latest my-nestjs-app
cd my-nestjs-app

Install Dependencies and Setup Stack

Terminal window
npm i tsx @thunder-so/thunder @vendia/serverless-express --save-dev

Create Lambda Handler

Create a Lambda handler file to bootstrap your NestJS application:

src/lambda.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { configure } from '@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;
}
export const handler = async (event, context) => {
const server = await bootstrapServer();
return server(event, context);
};

Setup Stack

stack/index.ts
import { Cdk, Lambda, type LambdaProps } from "@thunder-so/thunder";
const fnProps: LambdaProps = {
env: {
account: 'your-account-id',
region: 'us-east-1'
},
application: 'your-application-id',
service: 'your-service-id',
environment: 'production',
functionProps: {
codeDir: 'dist',
handler: 'lambda.handler',
include: [
'node_modules',
'lambda.js',
],
exclude: ['node_modules/.npmignore', '**/*.ts', '**/*.map'],
},
};
new Lambda(
new Cdk.App(),
`${fnProps.application}-${fnProps.service}-${fnProps.environment}-stack`,
fnProps
);

Deploy

Before you deploy, run your build script to generate artifacts in the dist directory.

Terminal window
npm run build
npx cdk deploy --all --app="npx tsx stack/index.ts"

When the deployment is complete, you will see the API Gateway URL in the output. You can access your NestJS app at that URL.

Containerized Service Deployment


Deploy containerized NestJS applications using ECS Fargate and Application Load Balancer with the Fargate construct. This pattern is ideal for long-running services, full-stack applications, and when you need persistent connections or WebSocket support.

Install Dependencies and Setup Stack

Terminal window
npm i tsx @thunder-so/thunder --save-dev
stack/index.ts
import { Cdk, Fargate, type FargateProps } from "@thunder-so/thunder";
const svcProps: FargateProps = {
env: {
account: 'your-account-id',
region: 'us-west-2'
},
application: 'your-application-id',
service: 'your-service-id',
environment: 'production',
rootDir: '', // e.g. 'app' for monorepos
};
new Fargate(
new Cdk.App(),
`${svcProps.application}-${svcProps.service}-${svcProps.environment}-stack`,
svcProps
);

Build Settings Using Nixpacks

Configure automatic containerization with Nixpacks:

stack/index.ts
const svcProps: FargateProps = {
// ... other props
buildProps: {
buildSystem: 'Nixpacks',
installcmd: 'npm install',
buildcmd: 'npm run build',
startcmd: 'npm run start:prod',
},
};

Build Settings Using Docker Container

Alternatively, use a custom Dockerfile:

Dockerfile
FROM public.ecr.aws/docker/library/node:20-alpine AS base
FROM base AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
EXPOSE 3000
CMD ["node", "dist/main"]
stack/index.ts
const svcProps: FargateProps = {
// ... other props
serviceProps: {
dockerFile: 'Dockerfile',
port: 3000,
},
};

Environment Variables and Secrets

Configure runtime environment variables and secrets:

stack/index.ts
const svcProps: FargateProps = {
// ... other props
serviceProps: {
variables: [
{ NODE_ENV: 'production' },
{ API_URL: 'https://api.example.com' }
],
secrets: [
{
key: 'DATABASE_URL',
resource: 'arn:aws:secretsmanager:us-west-2:123456789012:secret:/my-app/DATABASE_URL-abc123'
},
],
},
};

Deploy

Build and deploy your containerized application:

Terminal window
npm run build
npx cdk deploy --all --app="npx tsx stack/index.ts"

After deployment, you’ll receive an Application Load Balancer URL to access your containerized NestJS application.