Commands, Handlers, and the Command Bus
Model write operations as commands dispatched through CommandBus to dedicated handlers.
Why Commands Exist
In a CQRS system we split the model into two halves: the write side that changes state and the read side that returns data. A Command represents an intent to change state, for example CreateOrder or CancelSubscription.
- A command is a plain DTO carrying the data needed to perform the write.
- It is named in the imperative (do this) and describes a single business action.
- It returns at most an identifier or acknowledgment, never a full read model.
NestJS ships @nestjs/cqrs, which gives us a CommandBus to dispatch commands to exactly one handler.
Modeling a Command
A command is just a class. It holds the input data as readonly properties so it stays immutable once created. There is no logic inside it.
Below, CreateOrderCommand captures everything a handler needs to create an order. Notice it carries no NestJS decorators and no behavior.
export class CreateOrderCommand {
constructor(
public readonly customerId: string,
public readonly items: { sku: string; quantity: number }[],
public readonly currency: string,
) {}
}All lessons in this course
- Commands, Handlers, and the Command Bus
- Queries and Read-Model Projections
- Domain Events and AggregateRoot
- Sagas for Long-Running Workflows