nestjs-deployment · diff
git:20260914.5e8ef0f to git:20261018.e46f918
10 added, 116 removed. Audit A to A.
---
name: nestjs-deployment
description: 'Productionizes NestJS apps for containers. Use for multi-stage Docker builds of NestJS or Nx apps, webpack externals, migrations at deploy time, health checks, CORS and rate limiting, production logging, or deploying to a cloud platform.'
---
# NestJS Deployment Patterns
- Patterns for taking NestJS applications from development to production with Docker, proper bundling, database migrations, and security hardening. Extracted from production deployments on DigitalOcean App Platform but adaptable to any cloud provider.
-
- ## Activation scope
-
- This skill activates **per-module during Stage B** of the SaaS bootstrap, typically against a `deploy-docker` or `deploy-ci` roadmap item. It is NOT part of the Stage A foundation produced by `saas-workspace-initializer` — Stage A only sets up minimal lint/test CI. Reach for this skill when productionizing the deployment pipeline, not before there is anything to deploy.
-
- ## Deployment Checklist
-
- Before shipping to production, verify every item:
-
- - [ ] Multi-stage Docker build (builder, deps, runtime)
- - [ ] Webpack externals for problematic packages
- - [ ] Database migration on deploy (`prisma migrate deploy`)
- - [ ] Health check endpoint (`/api` or `/api/health`)
- - [ ] Non-root container user
- - [ ] Environment-driven configuration (`ConfigService`)
- - [ ] Rate limiting (`@nestjs/throttler`)
- - [ ] CORS restricted to frontend URL
- - [ ] Input validation pipeline (`ValidationPipe`)
- - [ ] Production logging levels (no debug/verbose)
- - [ ] Memory limits (`--max-old-space-size`)
- - [ ] `.dockerignore` excludes unnecessary files
-
- ## Architecture
-
- ```
- [Development]
- Dockerfile.dev
- -> Full dependencies (dev + prod)
- -> Volume mounts for hot reload
- -> nx serve for development server
- -> Health check on /api
-
- [Production]
- Dockerfile (multi-stage)
- Stage 1: Builder
- -> Install ALL deps, copy source
- -> npx nx build app-name
- -> Generate Prisma client
-
- Stage 2: Dependencies
- -> Copy generated package.json from builder
- -> npm install --omit=dev
- -> Explicitly install webpack externals
-
- Stage 3: Runtime
- -> node:24-alpine minimal image
- -> Non-root user (nestjs:nodejs)
- -> Copy: node_modules, built app, Prisma files
- -> Regenerate Prisma client (Alpine binaries)
- -> Health check, memory limits
- -> CMD: prisma migrate deploy && node main.js
- ```
-
- ## Quick Start: Minimal Production Dockerfile
-
- ```dockerfile
- # Stage 1: Build
- FROM node:24-alpine AS builder
- WORKDIR /app
- RUN apk add --no-cache openssl libc6-compat
- COPY package.json package-lock.json nx.json tsconfig.base.json ./
- COPY apps/my-api ./apps/my-api/
- COPY libs ./libs/
- RUN npm ci
- RUN cd apps/my-api && npx prisma generate
- RUN npx nx build my-api --configuration=production
-
- # Stage 2: Production deps
- FROM node:24-alpine AS deps
- WORKDIR /app
- RUN apk add --no-cache openssl libc6-compat
- COPY --from=builder /app/dist/apps/my-api/package.json ./
- RUN npm install --omit=dev
-
- # Stage 3: Runtime
- FROM node:24-alpine AS production
- WORKDIR /app
- RUN apk add --no-cache openssl libc6-compat
- RUN addgroup --system --gid 1001 nodejs && \
- adduser --system --uid 1001 nestjs
- COPY --from=deps /app/node_modules ./node_modules
- COPY --from=builder /app/dist/apps/my-api ./
- COPY --from=builder /app/apps/my-api/prisma ./prisma/
- RUN npx prisma generate --schema=prisma/schema.prisma
- RUN chown -R nestjs:nodejs /app
- USER nestjs
- EXPOSE 3000
- ENV NODE_ENV=production
- ENV NODE_OPTIONS="--max-old-space-size=450"
- HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
- CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api || exit 1
- CMD ["sh", "-c", "npx prisma migrate deploy && node main.js"]
- ```
-
- ## Quick Start: Production main.ts
-
- The production `bootstrap()` is where every global concern converges, and order matters. It must: pick log levels from `NODE_ENV` (no `debug`/`verbose` in production); create the app with `rawBody: true` so webhook HMAC verification can read the unparsed body; register the cookie parser; install a global `ValidationPipe` with `whitelist`, `forbidNonWhitelisted` and `transform`; restrict CORS to the configured frontend URL with `credentials: true`; and set the `api` global prefix while excluding webhook paths.
-
- For the full annotated implementation, plus the table explaining each setting, see [production-hardening.md](references/production-hardening.md).
-
- ## Decision Matrix
-
- | Need | Pattern | Reference |
- | ------------------------------- | ---------------------- | ------------------------------------------------------------- |
- | Docker build for NestJS + Nx | Multi-stage Dockerfile | [docker-multistage.md](references/docker-multistage.md) |
- | Packages break when bundled | Webpack externals | [webpack-bundling.md](references/webpack-bundling.md) |
- | DB schema sync on deploy | Migration on startup | [database-migrations.md](references/database-migrations.md) |
- | CORS, rate limiting, validation | Production hardening | [production-hardening.md](references/production-hardening.md) |
- | Health checks, logging, memory | Production hardening | [production-hardening.md](references/production-hardening.md) |
+ ## Apply
- ## References
+ - Use this during a Stage B deployment task after the app and its runtime dependencies are known.
+ - Produce a runtime image with the compiled app, production dependencies, and migration assets; verify packages that cannot be bundled before choosing externals.
+ - Run `prisma migrate deploy` in the container start command before serving traffic. Keep readiness dependent on required services and preserve a rollback path.
+ - Keep validation, CORS, throttling, security headers, health checks, and structured logging active in production.
- Load these for detailed implementation guidance:
+ ## Load by task
- - [docker-multistage.md](references/docker-multistage.md) - Multi-stage Docker builds for dev and production, docker-compose, .dockerignore
- - [production-hardening.md](references/production-hardening.md) - Security, CORS, rate limiting, validation, logging, health checks, memory management
- - [database-migrations.md](references/database-migrations.md) - Prisma migration strategy, PrismaService pattern, deploy workflow, rollback
- - [webpack-bundling.md](references/webpack-bundling.md) - NestJS webpack config, externals for problematic packages, package.json generation
+ - For image stages, runtime files, compose, and ignore rules, load [Docker builds](references/docker-multistage.md).
+ - For CORS, validation, throttling, logging, health checks, and memory, load [production hardening](references/production-hardening.md).
+ - For Prisma deploy migrations and rollback, load [database migrations](references/database-migrations.md).
+ - For native packages or libraries that break when bundled, load [webpack bundling](references/webpack-bundling.md).