Skip to content

Event Bus & Domain Events

DomusJS includes an Event Bus system designed to handle and propagate Domain Events across your application. This enables building event-driven architectures (EDA) that are modular, decoupled, and highly scalable.

✅ Emit domain events when key actions happen.
✅ Subscribe handlers to react to events asynchronously.
✅ Swap infrastructure (in-memory, RabbitMQ, Google Pub/Sub) without changing business logic.


A Domain Event represents something that has happened in your system that other parts may care about.

Examples:

  • UserRegisteredEvent
  • VideoUploadedEvent
  • PaymentProcessedEvent

Unlike commands or queries, events do not control flow — they announce facts.


In DomusJS:

  • You publish events to the Event Bus.
  • Registered handlers subscribe and react to those events.

Example event:

export class UserRegisteredEvent implements DomainEvent {
static TYPE = 'USER_REGISTERED';
readonly type = UserRegisteredEvent.TYPE;
constructor(
public readonly userId: string,
public readonly email: string,
public readonly occurredAt: Date = new Date()
) {}
}

Example handler:

export class SendWelcomeEmailHandler implements EventHandler<UserRegisteredEvent> {
async handle(event: UserRegisteredEvent): Promise<void> {
// Logic to send welcome email
}
}

eventBus.register(UserRegisteredEvent, new SendWelcomeEmailHandler());

When you publish an event:

await eventBus.publish([
new UserRegisteredEvent(user.id, user.email),
]);

All registered handlers will be called asynchronously.


  • Decouples event producers from consumers.
  • Enables modular, pluggable features (e.g., analytics, notifications).
  • Supports asynchronous, scalable processing.
  • Can switch between in-memory or external brokers (RabbitMQ, Google Pub/Sub) without changing domain code.

ImplementationUse Case
InMemoryEventBusSimple, local event handling (tests, dev).
RabbitMQEventBusDistributed event handling over RabbitMQ.
GooglePubSubEventBusCloud-native event distribution on GCP.

  • Events are fire-and-forget — don’t expect immediate responses.
  • Make handlers idempotent: they might be called more than once.
  • Use retries and dead-letter queues for production setups.