NestJS REST API Best Practices That Scale
Module boundaries, DTO validation, guards, exception filters and configuration: the NestJS structure that stays clean as your API grows.
Docker removes the "works on my machine" problem. A good image is small, fast to build and safe to run.
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]
The first stage has all build tools. The final image keeps only compiled code and production dependencies, so it is much smaller.
Copy package.json and install dependencies before copying the rest of the code. Docker reuses the cached install layer until your dependencies actually change.
Exclude node_modules, .git, .env and build output. It speeds up builds and keeps secrets out of the image.
The USER node line drops privileges. If the app is ever compromised, the attacker has far fewer rights.
services:
api:
build: .
ports: ["5000:5000"]
env_file: .env
depends_on: [db]
db:
image: postgres:16
volumes: [pgdata:/var/lib/postgresql/data]
volumes:
pgdata:
One command, docker compose up, starts the whole stack.
Add a /health endpoint and a container health check so orchestrators can restart a stuck instance.
Multi-stage builds, smart layer ordering, a non-root user and a compose file get you a clean, reproducible setup.
Module boundaries, DTO validation, guards, exception filters and configuration: the NestJS structure that stays clean as your API grows.
Schema design, migrations, relations, transactions and performance tips for using Prisma with PostgreSQL, MySQL or MongoDB.
Implement secure login with short-lived access tokens, rotating refresh tokens and httpOnly cookies, and avoid the common JWT mistakes.