Messaging
Core Principles
- Wolverine is the recommended default — MIT licensed, combines mediator + messaging in one library with built-in outbox, saga support, and convention-based handlers. MassTransit is an alternative but requires a commercial license from v9.
- Outbox pattern for reliability — Always use the transactional outbox to ensure messages are published only when the database transaction succeeds.
- Choreography for simple flows, saga for complex — If a workflow has 2-3 steps, use event choreography. If it has compensating actions or complex state, use a saga.
- Messages are contracts — Put message types in a shared contracts project. Keep them as simple records with primitive types.
Patterns
Wolverine Setup
Why: UseWolverine() registers handler discovery, transport, and outbox in one place. AutoProvision() eliminates manual broker setup during development.
Publishing Events
Wolverine supports two publishing styles: cascading messages (return values) and explicit publishing.
Why: Cascading messages (tuple return) are simpler and testable — the handler is a pure function. Use explicit IMessageBus when publishing is conditional or requires multiple events.
Consuming Events
Wolverine uses convention-based handlers — no interface, no base class. Just a Handle method with the message type as the first parameter.
Why: Convention-based handlers have zero ceremony. Wolverine discovers them by signature: any public method named Handle/HandleAsync/Consume/ConsumeAsync with the message type as the first parameter.
Transactional Outbox
Ensures messages are only published if the database transaction succeeds.
Why: AddDbContextWithWolverineIntegration + AutoApplyTransactions wraps every handler in a transaction that includes outbox writes. Messages are only sent after the transaction commits — no dual-write problem.
Saga (Stateful Orchestration)
Wolverine sagas use a Saga<T> base class with Start and Handle methods. Cascading messages drive the saga forward.
Why: Wolverine sagas use simple C# methods instead of a state machine DSL. Each handler returns cascading messages to drive the workflow. MarkCompleted() cleans up the saga state.
Alternative: MassTransit
MassTransit is a mature alternative with a commercial license requirement from v9+. Key API surface:
License note: MassTransit v9+ requires a commercial license for production use. Wolverine (MIT) is the recommended default for new projects.


