Skip to content

Blog

Who can dispatch on the CQRS bus?

In a CQRS codebase, every component eventually faces the question: can I dispatch a command or a query from here? The answer is almost never obvious, and most discussions online either say "yes, always" or "never except controllers", without explaining the reasoning behind either position.

Your domain should never import a logger

A call to $this->logger->info() inside an entity looks harmless. It is one line, it does not change any state, and everybody agrees that logging is useful. Yet from that line on, your domain imports a technical interface, your unit tests need a mock to instantiate the entity, and the layer that is supposed to depend on nothing already depends on something.

Events are facts, the bus is plumbing

A domain event describes something that already happened. It is a fact, not an intention. Yet many codebases publish events from inside the entity, at the moment its state changes, which couples the entity to infrastructure and lets you announce a fact before it is even true in the database.

The third mode: when bus and direct coexist

Most architecture discussions treat the bus question as global. Either the whole application routes commands and queries through a CQRS bus, or none of it does. That framing forces a bad trade: pay CQRS boilerplate on a homepage that displays a greeting, or drop the bus on a module that genuinely needs events and transactions. The real unit of decision is not the application. It is the module.