Deploying NestJS Applications: Best Practices

@rnab
3 min readJan 9, 2025

--

NestJS has become one of the most popular frameworks for building efficient and scalable server-side applications. It leverages TypeScript and modern JavaScript, making it a favorite among many developers. However, deploying NestJS applications can be daunting if you’re not familiar with the best practices and various tools at your disposal. In this article, we will dive into best practices for deploying NestJS applications seamlessly.

1. Build Optimization

Before deployment, the build process needs to be optimized. Optimize your application to ensure that you are shipping the smallest possible bundle.

Typescript Compiler Options

Optimize your tsconfig.json to ensure that unnecessary code isn’t included:

{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"noImplicitAny": true,
"removeComments": true,
"sourceMap": false,
"outDir": "./dist",
"rootDir": "./src",
"strict": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}

Tree Shaking

Use tree shaking to remove dead code from your production build. This can be achieved using tools like webpack or rollup.

For example, using webpack, you can create a webpack.config.js:

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
entry: './src/main.ts',
target: 'node',
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(),
],
};

2. Environment Configuration

Use environment variables to manage different settings for development, testing, and production.

config.module file

NestJS provides a handy library @nestjs/config that can be used to manage configuration settings:

// src/configuration.ts
export default () => ({
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
},
});

Validate Environment Variables

Use a validation library like class-validator and class-transformer to ensure that critical environment variables are set properly:

// src/env.validation.ts
import { plainToInstance } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, validateSync } from 'class-validator';

class EnvironmentVariables {
@IsString()
@IsNotEmpty()
DATABASE_HOST: string;

@IsNumber()
@IsNotEmpty()
DATABASE_PORT: number;
}

export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToInstance(EnvironmentVariables, config, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, { skipMissingProperties: false });

if (errors.length > 0) {
throw new Error(errors.toString());
}
return validatedConfig;
}

3. Dockerize Your Application

Containerize your application using Docker for consistency across various environments.

Dockerfile

Here’s a basic Dockerfile for a NestJS application:

# Base image
FROM node:14-alpine

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install --production

# Copy remaining application files
COPY . .

# Build the application
RUN npm run build

# Expose the application port
EXPOSE 3000

# Start the application
CMD ["node", "dist/main"]

Docker Compose (optional)

For more complex setups involving databases, use docker-compose:

version: '3'
services:
app:
build: .
ports:
- '3000:3000'
environment:
DATABASE_HOST: db
DATABASE_PORT: 5432
db:
image: postgres
environment:
POSTGRES_DB: nest
POSTGRES_USER: nest
POSTGRES_PASSWORD: nest_password
ports:
- '5432:5432'

4. Continuous Integration/Continuous Deployment (CI/CD)

Automate your deployment processes using CI/CD pipelines.

GitHub Actions Example

Here’s an example using GitHub Actions to build and deploy your containerized NestJS application:

name: CI/CD

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm install
- run: npm run build
- name: Build Docker Image
run: docker build . -t my-nest-app:latest
- name: Log into Docker Hub
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
- name: Push to Docker Hub
run: docker push my-nest-app:latest
- name: Deploy to Kubernetes
# Add deployment steps like kubectl apply -f k8s/deployment.yaml
run: echo "Deploying to Kubernetes"

Conclusion

Deploying a NestJS application can be streamlined by following best practices in build optimization, environment configuration, containerization, and CI/CD. By leveraging modern tools and methodologies, you can ensure your application is robust, scalable, and easy to maintain.

I hope you found this guide useful! Feel free to leave comments or questions below, and happy deploying!

--

--

@rnab
@rnab

Written by @rnab

Typescript, Devops, Kubernetes, AWS, AI/ML, Algo Trading

Responses (2)