A production-ready, scalable NestJS starter kit designed with Domain-Driven Design (DDD), Clean Architecture, and CQRS principles. This boilerplate is optimized for complex enterprise applications requiring strict separation of concerns, high maintainability, and ease of testing.
This project follows the Dependency Rule: Dependencies only point inwards.
- Domain Layer (Inner Core): Entities, Aggregate Roots, Repository Interfaces, Domain Events. (Zero external dependencies).
- Application Layer: Use Cases (Commands/Queries), Command Handlers, DTOs, Ports.
- Infrastructure Layer: Database implementations (TypeORM), Adapters, External APIs.
- Presentation Layer (Outer): HTTP Controllers, Resolvers, Request Validation.
- Modular Vertical Slices: Modules are self-contained (e.g., Users, Orders)
- CQRS Pattern: Segregated Command (Write) and Query (Read) responsibilities using
@nestjs/cqrs - Database: PostgreSQL with TypeORM (configured with migrations,
synchronize: falsefor safety) - Docker Ready: Multi-stage build Dockerfile and docker-compose for local development
- Security: Helmet, Rate Limiting, CORS, and strict Validation Pipes
- Authentication: JWT Strategy skeleton with clean Guard abstraction
- Observability: High-performance JSON logging via
nestjs-pino - Configuration: Validated Environment variables using Joi
- Path Aliases: Clean imports using
@modules,@common, etc.
- Node.js: v18 or v20+
- Docker & Docker Compose
- npm
Clone the repository and install dependencies:
git clone https://github.com/Henabakos/nestjs-enterprise-cqrs.git
cd nestjs-enterprise-cqrs
npm installCreate a .env file in the root directory:
cp .env.example .envEnsure your .env looks like this for local development:
NODE_ENV=development
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=root
DB_NAME=nest_cqrs
JWT_SECRET=super_complex_secret_key_change_me
JWT_EXPIRATION=1dStart the PostgreSQL container:
docker-compose up -d postgresImportant: This project uses synchronize: false. You must run migrations to create the database schema.
# 1. Generate migration file (if you made changes to entities)
npm run migration:generate -- src/database/migrations/Init
# 2. Apply migrations to the database
npm run migration:run# Development mode (Watch)
npm run start:dev
# Production mode
npm run start:prodSwagger UI: http://localhost:3000/api
API Root: http://localhost:3000/v1
src/
├── common/ # Global Filters, Guards, Interceptors, Decorators
├── config/ # Env validation and Config services
├── database/ # Data Source setup & Migrations
├── modules/ # Feature Modules (Vertical Slices)
│ └── orders/
│ ├── domain/ # Entities, Repository Interfaces, Events
│ ├── application/ # Commands, Queries, Handlers
│ ├── infrastructure/ # TypeORM Schemas, Repository Impl
│ ├── presentation/ # Controllers, DTOs
│ └── orders.module.ts
├── app.module.ts
└── main.ts| Command | Description |
|---|---|
npm run start:dev |
Runs the app in watch mode |
npm run build |
Compiles the app to /dist |
npm run migration:generate -- <path> |
Generates a migration file based on entity changes |
npm run migration:run |
Applies pending migrations to the DB |
npm run migration:revert |
Reverts the last migration |
npm run lint |
Lints and fixes code style issues |
npm run format |
Formats code using Prettier |
To run the entire application stack (Node.js App + PostgreSQL) strictly via Docker:
docker-compose up --buildNote: The docker-compose.yml sets DB_HOST=postgres automatically for the app container.
# Unit tests
npm run test
# e2e tests
npm run test:e2e
# Test coverage
npm run test:covThis project is open source and available under the MIT License.
Built with ❤️ by Hena
Code less, Architect more.