Skip to content

Buses

DomusJS includes three core buses to implement CQRS and event-driven architectures:

Command Bus → Handles actions that change state.
Query Bus → Handles data retrieval requests.
Event Bus → Publishes and distributes domain events.

These buses provide clean separation between application concerns and make it easy to extend or swap implementations.


  • Dispatches commands to their corresponding handlers.
  • Used for operations that change system state.

The infrastructure module ships with InMemoryCommandBus, which uses tsyringe to resolve handlers.

const commandBus = container.resolve<CommandBus>('CommandBus');
await commandBus.dispatch(new CreateUserCommand(...));

You can swap in your own implementation (e.g., using RabbitMQ):

container.register<CommandBus>('CommandBus', { useClass: RabbitMQCommandBus });

✅ As long as it follows the CommandBus interface, it integrates smoothly.


  • Handles read-only operations.
  • Returns data without modifying system state.

The InMemoryQueryBus is provided by default:

const queryBus = container.resolve<QueryBus>('QueryBus');
const user = await queryBus.ask(new GetUserByIdQuery(userId));

You can create wrappers (e.g., for caching, logging) or distributed setups:

container.register<QueryBus>('QueryBus', { useClass: DistributedQueryBus });

✅ This makes reads scalable and modular.


  • Publishes domain events to subscribed handlers.
  • Enables decoupled, reactive architectures.

The InMemoryEventBus works out of the box for synchronous, in-process eventing.

const eventBus = container.resolve<EventBus>('EventBus');
await eventBus.publish([new UserRegisteredEvent(...) ]);

DomusJS already includes ready-to-use implementations for distributed eventing:

RabbitMQRabbitMQEventBus
Google Pub/SubGooglePubSubEventBus

To use them, simply register them inside your registerDomusCore() call:

registerDomusCore({
eventBus: new RabbitMQEventBus(), // or GooglePubSubEventBus
});

✅ This enables cross-service event propagation for microservice architectures.


✅ Register all buses via registerDomusCore() or by overriding afterwards.
✅ Keep command, query, and event flows separate for clarity.
✅ Use middleware patterns (logging, metrics, tracing) around bus executions.
✅ For microservices, use distributed buses to communicate across services.