
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
You have built a modular API with NestJS, but running it locally differs vastly from operating it under load. To successfully deploy NestJS to production, you must move beyond simple npm start commands and address containerization, process management, and observability. This guide provides the exact configuration patterns I use to run enterprise-grade Node.js services reliably.
How do you optimize Docker images when you deploy NestJS to production?
The most common mistake engineers make when they first deploy NestJS to production is shipping the entire development dependency tree into the runtime container. NestJS relies heavily on TypeScript compilation and decorators during the build phase, but none of these tools are needed at runtime. A standard node:22 image with dev dependencies can easily exceed 1GB; a properly optimized production image should be under 250MB.
I recommend a three-stage Dockerfile. The first stage installs dependencies and compiles code. The second stage prunes production-only modules. The final stage copies only the compiled artifacts and pruned modules into a clean Alpine base. This approach eliminates vulnerabilities hidden in dev packages and drastically reduces cold-start times in serverless or auto-scaling environments.
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Prune
FROM node:22-alpine AS pruner
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
# Stage 3: Runtime
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nestjs && \
adduser -S nestjs -u 1001
COPY --from=pruner /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER nestjs
EXPOSE 3000
CMD ["node", "dist/main.js"] Notice the non-root user creation. Running Node.js as root inside a container is a critical security risk that fails most SOC 2 and ISO 27001 audits. If your team needs deeper guidance on securing Linux hosts before containerization, review our Ubuntu security hardening guide for foundational OS-level controls.
What is the best process manager to deploy NestJS to production?
NestJS runs on Node.js, which is single-threaded by default. In production, you must handle multiple CPU cores and automatic restarts on failure. The choice between PM2 and native container orchestration depends entirely on your infrastructure target.
| Criteria | PM2 (Ecosystem) | Kubernetes / ECS | Systemd (Bare Metal) |
|---|---|---|---|
| Scaling Model | Cluster mode (fork workers) | Horizontal Pod Autoscaler | Manual or script-based |
| Restart Policy | Built-in watchdog | Liveness probe + kubelet | OnFailure directive |
| Log Management | File-based rotation | stdout/stderr to collector | journald integration |
| Best For | VPS, legacy servers | Cloud-native microservices | Single-instance internal tools |
| Overhead | Low (~30MB RAM) | Medium (control plane cost) | Minimal |
If you are deploying to Kubernetes, do not use PM2. Kubernetes already handles process supervision, restarts, and scaling. Adding PM2 inside a pod creates a double-supervision problem where the container runtime and PM2 fight over process lifecycle. Instead, run node dist/main.js directly as PID 1. For VPS deployments without orchestration, PM2 cluster mode remains the gold standard for utilizing all available cores.
Configuring PM2 for Bare Metal
// ecosystem.config.js
module.exports = {
apps: [{
name: 'nestjs-api',
script: './dist/main.js',
instances: 'max', // Use all CPU cores
exec_mode: 'cluster',
autorestart: true,
max_memory_restart: '512M',
env_production: {
NODE_ENV: 'production',
PORT: 3000
}
}]
}; How do you configure health checks when you deploy NestJS to production?
Load balancers and orchestrators need to know if your application is actually serving traffic, not just running. NestJS provides the @nestjs/terminus module specifically for this purpose. Without proper health endpoints, rolling updates will cause downtime because the orchestrator cannot distinguish between a starting pod and a healthy one.
You need two distinct endpoints: /health/live for liveness (is the process alive?) and /health/ready for readiness (can it serve requests?). Liveness should be lightweight and never fail unless the process is truly deadlocked. Readiness should check database connections, cache availability, and external service dependencies.
// health.controller.ts
@Controller('health')
export class HealthController {
constructor(private health: HealthCheckService, private db: TypeOrmHealthIndicator) {}
@Get('live')
live() { return this.health.check([() => ({ status: 'ok' })]); }
@Get('ready')
ready() {
return this.health.check([
() => this.db.pingCheck('database', { timeout: 3000 }),
]);
}
} In Kubernetes, map these to your deployment spec. Set initialDelaySeconds high enough for NestJS bootstrap (usually 10–15s) and periodSeconds to 10. Misconfigured probes are the #1 cause of CrashLoopBackOff in new NestJS deployments.
How do you manage secrets and configuration securely?
Never commit .env files or hardcode credentials. When you deploy NestJS to production, configuration should be injected at runtime through environment variables or a dedicated secrets manager. NestJS’s @nestjs/config module validates configuration at startup, preventing silent failures from missing variables.
For teams managing PostgreSQL backends alongside their NestJS API, proper credential rotation and backup strategies are equally critical. Refer to our PostgreSQL backup and restore guide to ensure your data layer matches your application-layer security posture.
- Development: Use
.env.localwithdotenv, excluded from git. - Staging/Production (K8s): Use Kubernetes Secrets mounted as env vars or volumes.
- Production (Advanced): HashiCorp Vault or AWS Secrets Manager with dynamic credentials.
// config.validation.ts
export class EnvironmentVariables {
@IsString() DATABASE_URL: string;
@IsInt() PORT: number = 3000;
@IsEnum(['development', 'production']) NODE_ENV: string;
}
// app.module.ts
ConfigModule.forRoot({
validationSchema: classValidatorPlainToInstance(EnvironmentVariables),
validationOptions: { abortEarly: false },
}) This validation schema ensures your application fails fast at startup rather than crashing mid-request due to a typo in an environment variable name. Fast failure is preferable to partial operation in production systems.
What observability stack should you use for NestJS in production?
Logging console.log statements is insufficient for production debugging. You need structured JSON logs correlated with request IDs, plus metrics exposed in Prometheus format. NestJS integrates cleanly with OpenTelemetry for distributed tracing and Pino or Winston for structured logging.
Effective observability requires understanding the distinction between signals. Our article on metrics, logs, and traces compared explains when to use each signal type. For NestJS specifically, instrument every HTTP endpoint with trace spans, emit metrics for business KPIs (signups, payments), and log only actionable events at appropriate severity levels.
Enable the NestJS OpenTelemetry instrumentation package to automatically capture HTTP spans, database queries, and message queue operations. Export traces via OTLP to your preferred backend. For metrics, expose a /metrics endpoint using prom-client and scrape it with Prometheus. This setup gives you end-to-end visibility without modifying business logic.
Deploy NestJS to Production: Your Next Steps
Successfully operating NestJS in production requires treating the framework as a compiled, containerized service rather than a development convenience. Optimize your Docker builds with multi-stage pipelines, choose the right process manager for your infrastructure, implement proper health checks, validate configuration at startup, and instrument observability from day one. These practices separate hobby projects from systems that survive traffic spikes and compliance audits.
If your team needs hands-on support architecting cloud-native Node.js deployments or preparing infrastructure for SOC 2 certification, reach out to discuss your specific requirements. I help engineering teams ship faster while maintaining security and reliability standards.