Using Outbox allows for running endpoints with similar reliability to DTC while not actually using DTC.
Every time a message is processed, the copy of that message is stored in the persistent Outbox storage. Whenever a new message is received, the framework verifies if that message has been processed already by checking if it's present in the Outbox storage.
If the message is not found in the Outbox storage, then it is processed in a regular way as shown in the following diagram:
Processing a new incoming message consists of the following steps:
- The handlers processing that message are invoked.
- The downstream messages (messages sent during processing the message, e.g. from inside the handlers) are stored in a durable storage and business data is saved. Both operations are executed within a single transaction.
- The downstream messages are sent and marked as dispatched.
If the message is found in the Outbox storage, then it is treated as a duplicate and not processed again. However, even though the message has been processed and business data has been saved, it might happen that the framework failed to send downstream messages. In case the downstream messages are not marked as dispatched, they will be dispatched again.
at-least-oncemessage delivery, meaning that the downstream messages can be sent and processed multiple times. On the handler level, however, the Outbox guarantees
exactly-oncemessage processing, same as working with distributed transactions. This higher guarantee level is due to the deduplication that happens on the receiving side.
- The business data and deduplication data need to be stored in the same database.
- The Outbox feature works only for messages sent from NServiceBus message handlers.
- The endpoints using DTC can communicate with endpoints using Outbox only if either of the following conditions are satisfied:
- The endpoints using Outbox don't send messages to endpoints using DTC. However, endpoints using DTC can send messages to endpoints using Outbox.
- If endpoints using Outbox send messages to endpoints using DTC, then the handlers processing those messages are idempotent.
- The Outbox may generate duplicate messages if outgoing messages are successfully dispatched but the Mark as dispatched phase fails. This may happen for a variety of reasons, including Outbox storage connectivity issues and deadlocks.
In order to enable the Outbox for transports that don't support distributed transactions, e.g. RabbitMQ transport, use the following code API:
In order to enable the Outbox for transports that support distributed transactions, e.g. MSMQ or SQL Server transport, it is additionally required to add the following
<appSettings> <add key="NServiceBus/Outbox" value="true" /> </appSettings>
ReceiveOnly. A different level can be explicitly specified in configuration.
The Outbox feature requires persistence in order to store the messages and enable deduplication.