Skip to main content

Command Query Responsibility Segregation (CQRS)

Ferrox-Node strongly encourages the use of CQRS for complex microservices. This pattern separates the read model (Queries) from the write model (Commands).

The Command Bus​

When a client wants to mutate state (e.g., create an order, update a profile), the Controller must not execute the logic. Instead, it instantiates a Command object and dispatches it to the CommandBus.

import { Controller, Post } from '@ferrox/node';

@Controller('/api/v1/orders')
export class OrderController {
constructor(private commandBus: CommandBus) {}

@Post('/')
async createOrder(req: Request) {
const command = new CreateOrderCommand(req.body);
// The CommandBus automatically handles tracing and error formatting
return await this.commandBus.execute(command);
}
}

The Command Bus finds the appropriate Handler, wrapping the execution in observability traces and resilience patterns automatically.

The Query Bus​

For reading data, the Controller dispatches a Query object to the QueryBus. Queries are heavily optimized for read performance and often utilize Read Replicas, Datagrid projections, or Distributed Caching (Redis).

Event Sourcing & The Outbox Pattern​

When a Command successfully mutates state, it often emits a Domain Event. Ferrox-Node supports the Outbox Pattern: events are saved to the database in the same transaction as the state mutation. A background worker then publishes these events to Kafka or RabbitMQ, ensuring zero message loss even if the message broker is temporarily down during the transaction.