nestjs/cqrs: a small CQRS module bolted onto the Nest framework
A lightweight CQRS module for Nest framework (node.js) :balloon:
At a glance
- What is it?
- The @nestjs/cqrs package is a deliberately thin module that gives a Nest application command and query separation without pulling in a messaging broker or a persistence layer. Its value is mostly in how little it forces on you, and its limits are equally small: the repository documents almost nothing beyond the install step.
- Who is it for?
- The @nestjs/cqrs package fits a Nest team that wants to separate writes from reads inside one process and is willing to supply its own event bus, its own repository layer and its own tests, because the module supplies structure and nothing else. It does not fit a project that expects out-of-process messaging, persistence adapters or a migration path, since the repository ships no broker integration and no storage strategy.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the module actually contains
The description of the repository is a single line: a lightweight CQRS module for the Nest framework on node.js. Lightweight here is a design commitment rather than a marketing word, and the package layout backs it up. The published artifact is @nestjs/cqrs, and the package.json exposes one entry point, the root export, which resolves to ./dist/index.js with type declarations at ./dist/index.d.ts. The build output is plain compiled TypeScript produced by tsc against tsconfig.build.json, and the source lives in a single src directory alongside a test directory. There is no separate package for events, no separate package for sagas, and no second entry point for a bus implementation. Compare that with a framework that ships a broker adapter in the box: here the module is a set of abstractions your application wires into Nest's own dependency injection, and what you do beyond that is your problem.
One install command and a link to the Nest CQRS recipe
The installation section is one line, and the quick start is a link rather than a code sample.
$ npm install --save @nestjs/cqrsThe quick start points to an overview and CQRS tutorial hosted in the Nest documentation at docs.nestjs.com/recipes/cqrs, and the full API reference is expected to live there too. That is a meaningful design decision for a module inside a framework: the reference documentation is maintained in the framework's docs site, not in the repository, which keeps one source of truth but leaves the repository itself as a thin shell. The full API and options reference for this project is not in the repository. Anyone evaluating the module has to leave the repository to understand the API surface, and that is a fair thing to factor into a decision.
The peer dependency ranges tell you what it will bind to
The package.json is where the real constraints live, and they are strict. The engines field requires node ^20.19.0 or >=22.12.0, so older Node releases are excluded outright. The peer dependencies demand @nestjs/common and @nestjs/core at ^12.0.0, reflect-metadata at ^0.1.13 || ^0.2.0, and rxjs at ^7.2.0. The rxjs requirement is the one that tells you the module speaks in streams, since rxjs is the reactive primitive library Nest itself is built around, and a command or query bus that returns observables fits that shape naturally. Note that these are peer dependencies, so your application pins the versions and the module is tested against the range above. The development dependencies show the same generation: @nestjs/common, @nestjs/core and @nestjs/testing all at 12.1.1, typescript 7.0.2, vitest 4.1.11 and vite 8.3.1, with @types/node at 24.19.0.
The package is ESM-first with a CommonJS fallback
The exports map deserves a close look because it is a common source of friction in Nest projects.
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},The type field of the package is module, and the same file ./dist/index.js is served for both import and require, with a default fallback behind them. A single file serving both conditions means the build emits a module that Node can load either way, and the type declaration file is shared rather than duplicated per condition. The separate ./package.json export exists so tools can read the manifest through the package's own export map. For an application on Node 20.19 or later with a modern TypeScript setup this is all invisible, which is the point of getting it right in the package rather than in every consumer.
A release process built on release-it, commitlint and Renovate
The repository tells you how a version gets published, and the answer is a full release chain. The release script is release-it, driven by a .release-it.json configuration file, and the prepare script installs husky hooks, with a .husky directory and a .commitlintrc.json file in the tree, so commit messages are checked against a convention. There are two publish paths, publish:npm and publish:next, and the next path tags the release as next on npm rather than latest, which is how a pre-release reaches users without moving the default tag. Both are preceded by a build hook, and prerelease also runs a build. The scripts use release-it while Renovate is configured through renovate.json, so dependency updates are automated, and the lint and format tooling is oxlint plus prettier 3.9.9 with a .prettierrc file. There are two vitest configurations, vitest.config.ts and vitest.config.e2e.ts, with a separate test:e2e script, so unit and end-to-end tests are run apart.
The trade-off is that almost nothing is pre-built for you
The strength and the weakness of this package are the same property. Because the module is only a CQRS module, it does not decide where your events go. There is no broker adapter in the package layout, no database integration and no outbox pattern, and the repository carries no configuration file naming a transport. If you want command handlers to reach a separate service, or want projections to survive a restart, you write that integration yourself against your own messaging system of choice. The upside is that the module imposes no runtime infrastructure, so a team can adopt it inside an existing Nest application without adding a broker to its deployment. The downside is that a team hoping the library would deliver event sourcing, sagas, or a persistence layer will find none of it here, and the repository offers no comparison table or migration guide that would set those expectations before you start.
MIT licensing, a maintained tree, and version cadence
Licensing is uncomplicated. The package.json declares MIT, and the repository carries a LICENSE file, with the documentation noting that Nest is an MIT-licensed open source project. MIT places no restriction on commercial use, modification or redistribution beyond requiring the notice to travel with the code, and it says nothing about the behaviour of any infrastructure you connect it to, so the obligations attach to the library and not to your deployment. On maintenance, the tree is active: the last push was on 2026-10-19, and the release history shows 11.0.3 on 2025-03-24, 12.0.0 on 2026-08-27 and 12.1.0 on 2026-09-29. The major version jump from 11 to 12 in 2026 lines up with the peer dependency ranges, which moved to @nestjs/common and @nestjs/core at ^12.0.0, so a major release of Nest is a major release here too, and an upgrade means re-checking that range rather than reading a changelog in this repository.
Editorial conclusion
The @nestjs/cqrs package fits a Nest team that wants to separate writes from reads inside one process and is willing to supply its own event bus, its own repository layer and its own tests, because the module supplies structure and nothing else. It does not fit a project that expects out-of-process messaging, persistence adapters or a migration path, since the repository ships no broker integration and no storage strategy. Before adopting it, read the CQRS recipe in the Nest documentation, which the project points to as its quick start, and check the peer dependency ranges in package.json, since the module requires @nestjs/common and @nestjs/core at ^12.0.0 and reflect-metadata ^0.1.13 or later.
Frequently asked questions
How do I install the Nest CQRS module?
Run npm install --save @nestjs/cqrs. The package requires Node ^20.19.0 or >=22.12.0 and expects @nestjs/common and @nestjs/core at ^12.0.0 as peer dependencies.
Where is the API documentation for @nestjs/cqrs?
The README points to an overview and CQRS tutorial in the Nest documentation at docs.nestjs.com/recipes/cqrs as the quick start. The repository itself does not contain the full API reference, so the framework documentation site is the source to read.
Does @nestjs/cqrs include a message broker or database integration?
No. The package exposes a single root export built from a src directory and compiled by tsc, with no broker adapter, storage layer or separate entry point. Bringing your own event transport and persistence is part of adopting it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nestjs-cqrs)