NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. Built with TypeScript by default, it combines elements of object-oriented programming, functional programming, and functional reactive programming. Deploying NestJS to production requires proper TypeScript compilation, build configuration, and server setup.
With Out Plane, you can deploy your NestJS application in under a minute. This guide shows you exactly how.
What You'll Need
Before starting, make sure you have:
- Node.js 20+ installed on your machine
- npm (comes with Node.js)
- A GitHub account
- A NestJS application in a GitHub repository
Don't have Node.js installed? Download it from nodejs.org:
- Windows: Download the LTS installer from nodejs.org
- macOS: Use
brew install nodeor download from nodejs.org - Linux: Run
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt install -y nodejs(Ubuntu/Debian)
Once Node.js is installed, create a new NestJS project:
npx @nestjs/cli new my-nestjs-app
cd my-nestjs-appIf you don't have a NestJS app yet, use our example below.
Quick Start: Sample NestJS Application
Here's a minimal NestJS application you can use. Create a new project with the NestJS CLI:
npx @nestjs/cli new my-nestjs-app
cd my-nestjs-appThe CLI generates a project with the following key files. Update them for production deployment.
Replace src/app.controller.ts:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): { message: string; status: string } {
return this.appService.getHello();
}
@Get('health')
getHealth(): { status: string } {
return { status: 'healthy' };
}
}Replace src/app.service.ts:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): { message: string; status: string } {
return {
message: 'Hello from NestJS!',
status: 'running',
};
}
}Update src/main.ts to listen on the correct port and host:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
console.log(`Application running on port ${port}`);
}
bootstrap();The 0.0.0.0 host binding is required for the application to accept connections inside a container.
Create a Procfile in the project root (no file extension):
web: node dist/main.jsThis tells Buildpacks how to start your compiled NestJS application.
Push this code to a GitHub repository, and you're ready to deploy.
Optional: Add a Dockerfile
If you prefer full control over the build process, create a Dockerfile with multi-stage builds for smaller images:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 8080
CMD ["node", "dist/main.js"]This produces a lean production image with only compiled JavaScript and production dependencies. With a Dockerfile, select Dockerfile as your build method in the next step. Without one, select Buildpacks and Out Plane handles everything automatically.
Deploy in 3 Steps
Step 1: Connect Your Repository
- Go to console.outplane.com
- Sign in with your GitHub account
- Select your NestJS repository from the list
Out Plane automatically detects your Node.js application and configures the build process.
Step 2: Configure Your Application
Configure the following settings in the create application form:
Build Method
Select how Out Plane should build your application:
- Buildpacks (Recommended): Automatically detects Node.js, installs dependencies, runs
npm run build, and starts the application using yourProcfile. No additional configuration needed. - Dockerfile: Use this if you have a custom
Dockerfilein your repository for full control over the build process.
For most NestJS applications, Buildpacks is the easiest option.
Basic Settings
- Port: Set to
8080 - Branch: Select
mainor your preferred branch - Region: Choose the region closest to your users
Environment Variables (Optional)
If your application uses environment-specific configuration, add them here. For our simple example, no environment variables are required.
For more complex applications, you might add variables like database URLs or API keys using the Add button or Raw Edit for bulk entry:
DATABASE_URL=postgres://user:password@host/database
JWT_SECRET=your-jwt-secret
NODE_ENV=productionStep 3: Deploy
Click Deploy Application and watch the build process:
- Queued → Waiting for resources
- Building → Installing dependencies, compiling TypeScript
- Deploying → Starting your NestJS application
- Ready → Your app is live
Once the status shows Ready, your application is live. You can find your application URL at the top of the deployment page. Click the URL to open your NestJS app in a new tab. SSL is automatically configured.
Production Best Practices
Enable CORS
Configure Cross-Origin Resource Sharing for frontend applications:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: process.env.CORS_ORIGIN || '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
credentials: true,
});
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
}
bootstrap();Use Helmet for Security Headers
Install and configure Helmet to set secure HTTP headers:
npm install helmetimport helmet from 'helmet';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(helmet());
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
}
bootstrap();Enable Compression
Reduce response sizes with compression middleware:
npm install compression @types/compressionimport * as compression from 'compression';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(compression());
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
}
bootstrap();Global Validation Pipes
Use class-validator to automatically validate incoming request data:
npm install class-validator class-transformerimport { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
}
bootstrap();Proper Logging
Use the built-in NestJS logger for structured production logs:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: ['error', 'warn', 'log'],
});
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
Logger.log(`Application running on port ${port}`, 'Bootstrap');
}
bootstrap();Connecting a Database
Most NestJS applications need a database. Out Plane provides managed PostgreSQL:
- Go to Databases in the sidebar
- Click Create Database
- Select PostgreSQL version and region
- Copy the connection URL
Add the connection URL as an environment variable:
DATABASE_URL=postgres://user:password@host:5432/databaseUsing TypeORM
Install TypeORM and the PostgreSQL driver:
npm install @nestjs/typeorm typeorm pgConfigure TypeORM in your app.module.ts:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
url: process.env.DATABASE_URL,
autoLoadEntities: true,
synchronize: false,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Set synchronize: false in production. Use migrations instead to manage schema changes safely.
Using Prisma
Alternatively, use Prisma with NestJS:
npm install prisma @prisma/client
npx prisma initCreate a Prisma service:
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
async onModuleInit() {
await this.$connect();
}
async onModuleDestroy() {
await this.$disconnect();
}
}Register the service in your module and inject it wherever you need database access.
Custom Domain Setup
Replace the default .outplane.app URL with your own domain:
- Navigate to Domains
- Click Map Domain
- Enter your domain (e.g.,
api.yourdomain.com) - Add the DNS records shown to your domain registrar
SSL certificates are automatically provisioned once DNS propagates.
Monitoring Your Application
After deployment, monitor your NestJS application:
- Logs: View real-time application logs including NestJS bootstrap and request logs
- Metrics: Track CPU, memory, and network usage
- HTTP Logs: Analyze incoming requests, response times, and status codes
Access these from the sidebar in your application dashboard.
Troubleshooting
Build Fails with TypeScript Errors
Fix compilation errors before deploying. Run npm run build locally to verify your TypeScript compiles without errors. Check tsconfig.build.json for correct compiler settings.
Application Won't Start
Check the port configuration. Make sure you set the port to 8080 in the application settings. Your main.ts should read process.env.PORT and bind to 0.0.0.0.
Module Resolution Errors
Verify all dependencies are in package.json. NestJS uses dependency injection extensively. Missing providers or imports cause runtime errors. Check your application logs for the specific module that failed to resolve.
// Common error: forgot to import a module
@Module({
imports: [TypeOrmModule.forFeature([User])], // Must import entity modules
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}Memory Issues
Adjust Node.js memory limits. If your application runs out of memory during build or runtime, set the NODE_OPTIONS environment variable:
NODE_OPTIONS=--max-old-space-size=512For large applications with many modules, increase this value as needed.
Swagger Docs Not Accessible
Ensure Swagger is configured before listen. If you use @nestjs/swagger, make sure the setup runs before app.listen():
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('My API')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api/docs', app, document);
const port = process.env.PORT || 8080;
await app.listen(port, '0.0.0.0');
}
bootstrap();Access your API documentation at https://your-app.outplane.app/api/docs.
Next Steps
Your NestJS application is now deployed and running in production. Here's what to explore next:
- Scale your application: Adjust instance types and auto-scaling settings for higher traffic
- Set up CI/CD: Enable automatic deployments on every git push
- Add monitoring: Integrate with external monitoring tools via Out Plane's metrics export
- Build microservices: Use NestJS microservice transporters with Out Plane's internal networking
Summary
Deploying a NestJS application to Out Plane takes three steps:
- Connect your GitHub repository
- Configure port (8080), environment variables, and build method
- Deploy and get your live URL with automatic HTTPS
No server configuration, no manual SSL setup, no infrastructure management. Full support for TypeScript compilation, dependency injection, and modular architecture.
Ready to deploy your NestJS application? Get started with Out Plane and receive $20 in free credit.