The problem
Author: Tymoteusz Dzienniak
How to make sure that the publishing of an event is consistent with the outcomes of the business transaction that generated it? Without an outbox, we can use two different strategies for event publishing.
Publish after commit

If the transaction was committed successfully, but the publishing failed, the system is left in an inconsistent state: something happened, but the rest of the system doesn't know about this and can't react. For example, suppose we have the Payment service publishing a PaymentSucceeded event that is meant to trigger the shipping of the goods in the Shipment service. In that case, this shipment will never happen even though the payment is successful.
With this strategy, we get "at most once" delivery, which may be suitable for some less essential messages but is certainly not enough for critical business events.
Publish before commit

We can also publish an event before committing a transaction, but then we will have something called "phantom events" if the original transaction is rolled back. We published an event that is a statement of the fact (something happened in the system), but that fact was rolled back and is non-existent anymore. The rest of the system will react, but this reaction should not happen. If we consider the example from the previous paragraph: the Payment service sent an event PaymentSucceeded, but the payment was canceled. The Shipment service will process this event, and the goods will be shipped despite an unsuccessful payment.