Skip to content

Messaging Overview

Modulus provides a messaging abstraction over MassTransit for cross-module communication via integration events. It supports InMemory, RabbitMQ, and Azure Service Bus transports, and includes built-in transactional outbox and inbox patterns for reliable, exactly-once message delivery.

Why Abstract over MassTransit?

ConcernModulus Messaging
Swap transports freelySwitch between InMemory, RabbitMQ, and Azure Service Bus by changing a single enum value. No handler code changes required.
Cleaner handler interfaceImplement IIntegrationEventHandler<TEvent> instead of MassTransit's IConsumer<ConsumeContext<T>>. Less ceremony, more focus on business logic.
Automatic idempotencyEvery handler is transparently wrapped with IdempotentConsumerAdapter to prevent duplicate processing when the inbox store is registered.
Transactional outbox built-inSave domain state and outbox messages in the same database transaction. A background processor publishes them reliably to the broker.
Convention-based discoveryHandlers are auto-discovered from the assemblies you specify -- no manual MassTransit consumer registration.

Installation

If you scaffolded your solution with the Modulus CLI, the messaging package is already referenced. To add it manually:

bash
dotnet add package ModulusKit.Messaging

Quick Setup

Register messaging in your host project's Program.cs or composition root:

csharp
using Modulus.Messaging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddModulusMessaging(options =>
{
    options.Transport = Transport.RabbitMq;
    options.ConnectionString = "amqp://guest:guest@localhost:5672";
    options.Assemblies.Add(typeof(Program).Assembly);
});

You can add multiple assemblies to scan for handlers across all your modules:

csharp
builder.Services.AddModulusMessaging(options =>
{
    options.Transport = Transport.RabbitMq;
    options.ConnectionString = "amqp://guest:guest@localhost:5672";
    options.Assemblies.Add(typeof(CatalogModule).Assembly);
    options.Assemblies.Add(typeof(OrdersModule).Assembly);
    options.Assemblies.Add(typeof(PaymentModule).Assembly);
});

MessagingOptions Reference

PropertyTypeDefaultDescription
TransportTransport--The message broker transport to use. One of InMemory, RabbitMq, or AzureServiceBus.
ConnectionStringstring--Connection string for the selected transport. Not required for InMemory.
AssembliesList<Assembly>EmptyAssemblies to scan for IIntegrationEventHandler<T> implementations.
OutboxPollIntervalTimeSpan5 secondsHow often the OutboxProcessor polls for pending outbox messages.
OutboxBatchSizeint100Maximum number of outbox messages to process per polling cycle.

Handler auto-discovery

AddModulusMessaging scans the provided assemblies for all IIntegrationEventHandler<TEvent> implementations. Each handler is wrapped with IdempotentConsumerAdapter<TEvent> and registered as a MassTransit consumer automatically. No manual consumer registration is needed.

How It Works

At a high level, the messaging system works as follows:

  1. Module A publishes an integration event via IMessageBus.
  2. MassTransit serializes and sends the event to the configured broker.
  3. The broker (RabbitMQ, Azure Service Bus, or in-memory) routes the message to subscribers.
  4. IdempotentConsumerAdapter ensures the event has not already been processed (when an inbox store is registered).
  5. Your IIntegrationEventHandler receives and processes the event.

What's Next

Dive into the specific concepts:

  • Integration Events -- Define events and handlers for cross-module communication
  • Message Bus -- The IMessageBus API for publishing and sending messages
  • Transports -- Configure InMemory, RabbitMQ, or Azure Service Bus
  • Outbox Pattern -- Reliable message publishing with transactional outbox
  • Inbox Pattern -- Idempotent message consumption with the inbox pattern

Released under the MIT License.