Overview
Pipeline behaviors for NestJS CQRS — wrap every command, query, and event handler with reusable cross-cutting concerns (logging, validation, tracing, audit, …) using a clean middleware-like chain.
HTTP Request → Controller (schema validation) → CommandBus / QueryBus / EventBus → Pipeline chain: [global before] → [@UsePipeline behaviors] → [global after] → handlerFor the complete interactive map through all four Clean Architecture layers with clickable source links, see Runtime architecture.
Same-class override: if a handler’s
@UsePipelinedeclares the same behavior class as a globalbefore/afterentry, the behavior runs once at its global chain position, using the handler’s options. Preserving position keeps global security guards outside cache/idempotency behaviors that may short-circuit without callingnext().Global type-level guards do not replace entity checks or field filtering performed inside a handler. Because cache/idempotency hits skip that handler, their keys must include the relevant tenant, principal, and permission scope whenever results depend on those checks.
The core package adds no runtime dependencies beyond NestJS itself, apart from the
dependency-free @cqrs-ddd/uuidv7, @cqrs-ddd/safe-stringify and @cqrs-ddd/untyped.
@nestjs-pipeline/tenant, /correlation and /job-context depend on no other pipeline
package. Add-on packages use their own declared integrations (Zod, OpenTelemetry, CASL,
OpenFeature, etc.). Works with Express and Fastify.
Library scope
Section titled “Library scope”The packages are reusable libraries for external applications and future use
cases. api is one example, not the limit of the public contracts.
Repository caching and pipeline query-result caching are complementary. See
AGENTS.md for library scope and the criteria for reviewing or
removing features, and the
architecture skill for
cache layer ownership, command reads, invalidation and security.
Packages
Section titled “Packages”| Package | Description |
|---|---|
@nestjs-pipeline/core |
Pipeline engine, @UsePipeline decorator, PipelineModule, LoggingBehavior |
@nestjs-pipeline/correlation |
Standalone correlation ID propagation — HTTP middleware, @WithCorrelation, runWithCorrelationId, getCorrelationId, and correlationSource for pipelines and jobs |
@nestjs-pipeline/zod |
Zod v4 validation/parsing behavior that applies successful parsed object output to the request, plus zodBadRequest for Nest’s schema validation, ZodValidationFilter, ZodValidationError |
@nestjs-pipeline/opentelemetry |
OpenTelemetry tracing & metrics behaviors — spans plus duration/throughput/error instruments for every pipeline invocation, and AttributesBehavior for the add-ons’ span attributes |
@nestjs-pipeline/casl |
CASL authorization — type-level CaslBehavior fed by an application permission source, plus CaslAuthorizer (can, authorize, project, dependsOnEntity) for entity and field checks and abilityDigest for cache and replay scopes |
@nestjs-pipeline/resilience |
Resilience on cockatiel — named policies for outbound dependencies (retry, circuit breaker, timeout, bulkhead, fallback), shared through DI, and a behavior for handler-level retry, timeout and bulkhead |
@nestjs-pipeline/cache |
Read-through caching behavior for queries — pluggable stores (memory, redis, memcache, sqlite, postgres) via cache-manager v7 on keyv |
@nestjs-pipeline/feature-flags |
Feature-flag gating behavior — provider-agnostic via OpenFeature (Unleash shown in examples; Flagsmith/LaunchDarkly are drop-in alternatives) |
@nestjs-pipeline/deadletter |
Dead-letter capture for failed requests (events by default) — bundled BullMQ, RabbitMQ and Postgres transports; redrive with an attempt count and a resolved state for stored records |
@nestjs-pipeline/rate-limit |
Rate-limiting behavior — backend-agnostic via rate-limiter-flexible (memory, Redis/Valkey, Mongo, SQL), HTTP 429 filter |
@nestjs-pipeline/audit |
Audit-trail behavior — records who/what/outcome/duration to a pluggable AuditSink (console default, Postgres drop-in), with payload redaction |
@nestjs-pipeline/idempotency |
Idempotency behavior — atomic concurrent duplicate exclusion and successful-response replay per key; failed executions are retryable by default, via a pluggable store (in-memory default, Redis/Postgres drop-in) |
@nestjs-pipeline/tenant |
currentTenantId(), runWithTenant() and tenantSource — the current tenant, for code deep inside a handler and for pipelines and jobs |
@nestjs-pipeline/job-context |
Carries a request’s tenant, correlation id and principal into the queue jobs it enqueues (withJobContext, @InJobContext), and gives system work an explicit context (@AsSystem) |
Add-on packages live in
packages/pipeline-<name>/. Those that plug into the pipeline peer-depend on@nestjs-pipeline/core;tenant,correlationandjob-contextdepend on no pipeline package and are connected through module options (sources).
Framework-neutral packages, with no NestJS dependency:
| Package | Description |
|---|---|
@cqrs-ddd/core |
DDD building blocks — aggregates with versioned mutations, detached domain events, CommandBaseHandler, repository contracts, ORM-neutral persistence lifecycle decorators, a revision-fenced repository cache, tenant-scoped cache keys and HTTP status mapping |
@cqrs-ddd/mikro-orm |
MikroORM 7 adapters for @cqrs-ddd/core — AggregateRepository, version-conditioned writes, MikroOrmCache, MikroOrmDialect, the multi-tenant TenantStore |
@cqrs-ddd/uuidv7 |
RFC 9562 UUIDv7 generation and validation, with no dependencies |
@cqrs-ddd/safe-stringify |
A strict, key-sorted serializer for identities, a redacting serializer for logs, and the key-segment helpers, with no dependencies |
@cqrs-ddd/untyped |
untyped(value): a typed replacement for as any that reads undeclared properties as unknown, with no dependencies |
@nestjs-pipeline/coreuses the three utilities; import them from their own packages. No@nestjs-pipeline/*package uses@cqrs-ddd/core, and it knows nothing of them: an application connects the two.
Every package is at 0.4.2. CHANGELOG.md records each release.