NestJS CQRS Setup
Use this workflow to add or fix CQRS in NestJS with deterministic environment-based enable or disable behavior.
Prerequisites
- NestJS project with
src/main.tsand a root module (typicallysrc/app.module.ts). - Node.js runtime compatible with the project Nest major version.
- Package manager lockfile present (
package-lock.json,pnpm-lock.yaml, oryarn.lock).
Step 1: Preflight checks
- Run all commands from project root.
- Confirm required files exist:
src/main.ts- root module file (
src/app.module.tsor project equivalent)
- Detect package manager from lockfile and use only that manager for install and scripts.
- Detect Nest major version from
package.json(@nestjs/common). - If Nest 11 is detected, require Node.js 20+ before proceeding.
If preflight fails, stop and report the exact blocker before making edits.
Step 2: Install dependencies
Install required packages:
npm install @nestjs/cqrs @nestjs/config
Package-manager equivalents are allowed (pnpm add, yarn add) when matching the repository lockfile.
Step 3: Align package majors
Match package majors to the Nest major:
- Nest 11 ->
@nestjs/cqrs^11 and@nestjs/config^4 - Nest 10 ->
@nestjs/cqrs^10 and@nestjs/config^3
Resolve peer dependency or major-version mismatches before wiring modules.
Step 4: Add environment toggle
Create or update .env with a single CQRS gate:
CQRS_ENABLED=true
Behavior contract:
trueor unset: CQRS enabledfalse: CQRS disabled
Step 5: Wire AppModule deterministically
In the root module imports:
- Add
ConfigModule.forRoot({ isGlobal: true }). - Add
ConditionalModule.registerWhen(CqrsModule.forRoot(), 'CQRS_ENABLED'). - Gate CQRS-dependent feature modules with the same flag using
ConditionalModule.registerWhen(...).
Use the same toggle for infrastructure and CQRS-consuming modules to avoid DI failures when disabled.
Step 6: Wire feature modules and handlers
- In each CQRS feature module, import
CqrsModule. - Register command/query/event handlers in
providers. - Use
CommandBus,QueryBus, andEventBusonly in modules that are CQRS-enabled or conditionally imported.
Step 7: NodeNext and ESM safeguard
If tsconfig uses moduleResolution: "nodenext" or "node16", use .js file extensions in relative TypeScript imports.
Step 8: Verification gates
- Set
CQRS_ENABLED=true, run the app, and confirm startup without CQRS DI errors. - Execute one command and one query flow and confirm handlers run.
- Set
CQRS_ENABLED=false, restart, and confirm:- app still boots
- CQRS-gated modules are not loaded
- no
CommandBus/QueryBus/EventBusinjection failures occur
Failure handling
- If dependency installation fails, report exact failing command and error output, then stop before partial wiring.
- If required Nest files are missing, stop and request the correct project path.
- If existing architecture already contains CQRS setup, prefer minimal non-destructive edits.
References in this skill
- AppModule conditional wiring pattern: reference.md
- Minimal command/query flow: examples.md