Command
A request to change the state of the system, handled by a single handler in a CQRS architecture.
A command is an intent to change the state of the system. It's a verb in imperative form: PlaceOrder, CancelTraining, ConfirmPayment. Unlike an event, which describes something that already happened, a command asks the system to do something.
On an Event Storming board, commands are the blue sticky notes. They sit on the timeline as the entry points that lead to events.
A command handler is where you orchestrate the write side of your application. It typically loads an aggregate from a repository, calls domain methods on it, and saves the result. If the operation produces side effects, the handler publishes events that other parts of the system react to.
Commands don't return business data. They either succeed or fail. This is one of the core ideas behind CQRS: the write path (commands) and the read path (queries) are separate. If you need data after a write, you query for it through the read side. Returning an UUID along with a success status is fine.
In practice, a command is a plain struct with the data needed to perform the action:
type CancelTraining struct {
TrainingUUID string
UserUUID string
}
The handler receives this struct, validates the request against the current state, and applies the change. There's no HTTP context or database connection passed in.
References
- How to use basic CQRS in Go — Introduces commands and queries as the two sides of CQRS. Defines commands as operations that change state but don't return data, and walks through splitting an application service into separate command and query handlers.
- Combining DDD, CQRS, and Clean Architecture in Go — Shows how to orchestrate business logic with command handlers. Commands load aggregates from repositories, apply domain rules, and save results. Includes a practical CancelTraining command handler example.
- Increasing Cohesion in Go with Generic Decorators — Splits application logic into commands and queries, CQRS style, and wraps command handlers with generic decorators for logging, metrics, and tracing. Shows how multiple entry points route to the same command handler.
- Database Transactions in Go with Layered Architecture — Defines a UsePointsAsDiscount command and handler to demonstrate transaction management. The command handler uses injected repository interfaces and keeps business logic independent of database details.
- Distributed Transactions in Go: Read Before You Try — Shows replacing synchronous calls in a command handler with event publishing. The command handler publishes an event, and a separate subscriber maps the event payload back to a command for execution.
- Microservices test architecture. Can you sleep well without end-to-end tests? — Covers testing command handlers with mocked dependencies. Shows how CQRS and Clean Architecture make it easy to inject mocks and test complex orchestration in commands as unit tests.
- How to implement Clean Architecture in Go (Golang) — Describes ports as entry points to the application, including CLI commands and Pub/Sub subscribers. Ports execute application commands, while the application layer stays independent of how it's called.
- Watermill 1.3 released, an open-source event-driven Go library — Introduces a redesigned CQRS API with separate CommandProcessor and CommandBus components. Adds request-reply support for commands, allowing you to send a command and wait for a result.
- Synchronous vs Asynchronous Architecture — References CQRS as Command Query Responsibility Segregation and discusses the difference between commands and events. Explains why the API is similar but the semantics differ in practice.
- Unpopular opinions about Go — Discusses using Go generics to build decorators for application-level command handlers. Shows how metrics, logging, and tracing decorators work well with generic command handler signatures.
- AMA #1: Clean Architecture, Learning, Event-Driven, Go — Answers community questions about the difference between commands and events. Explains that while the API is similar, following the distinction between commands and events makes systems easier to reason about.