Wolverine for messaging

The problem it solves

Domains must react to one another — an invitation creates a notification, a deleted organization cancels its subscription — without calling one another. And the reaction must happen if and only if the change committed: an audit entry for a change that rolled back, or a lost webhook for one that succeeded, are both bugs.

That takes a message bus with a transactional outbox: the message is written in the same database transaction as the change, and sent once it commits.

Wolverine provides that outbox natively on EF Core and PostgreSQL, with RabbitMQ as the transport, exponential retries and dead-letter queues. Its core and the extensions the Starter uses are under the MIT licence. The Starter used MassTransit before; MassTransit became commercial with its version 9, and Wolverine replaced it with the same events and the same guarantees.

What it costs

  • A broker to run — RabbitMQ, in development and in production.
  • Eventual consistency across domains: a notification appears a moment after the invitation, not in the same transaction.
  • Outbox tables in their own schemas, built by the migration runner.
  • Some configuration is the Starter's own: Wolverine generates handler code by default; the Starter turns that off and registers each consumer explicitly, so that consumers can stay internal and nothing is compiled at runtime.

What you can relax

  • Change the transport or the library in one place. Only Blouppy.Infrastructure.Messaging references Wolverine (BusLibraryBoundaryTests enforces it); the domains use the Starter's own IIntegrationEventPublisher<T> and IIntegrationEventHandler<T>.
  • Keep a reaction synchronous when it must hold before the change: that is what domain events — inside the transaction — and .PublicData contracts are for. Not everything needs the bus.