Overview
The Transactional Outbox pattern guarantees the atomicity of database update transactions and the publication of messages by persisting them together with the updated data. It is one of the Transactional Messaging patterns, which as a category aim to guarantee atomicity of local transaction execution and message publication.
Problem
A microservice typically needs to publish a message when it performs a database update transaction — for example, in the Saga pattern. It becomes crucial to guarantee that the update and the sending of the message to another microservice are executed as a single transaction. Without this guarantee, if the database update fails, a message might still be published — or if message publication fails, the database may have been updated without notifying other services. Either outcome leads to inconsistencies in the system.
Solution
The Transactional Outbox approach guarantees atomicity by persisting messages together with updated data in the same transaction. The message publication itself is then handled by a separate complementary pattern — either Polling Publisher or Transaction Log Tailing.
Relational Databases
In a relational database, the Transactional Outbox consists of creating a specific table, called OUTBOX, to temporarily persist messages. Create, update, and delete operations must, within their transactions, insert the respective message into the OUTBOX table. Atomicity is thus guaranteed because both processes are executed within a single transaction, which in relational databases has the atomic property.
Non-relational Databases
The Transactional Outbox can also be applied to non-relational databases: each record in the database contains an attribute with a list of messages to be published after the operation executes. Atomicity is guaranteed because the data operation (insert, update, or delete) and the insertion of messages are implemented as a single atomic operation.
Trade-offs
Benefits
- Guarantees atomicity between database writes and message publication
- Prevents inconsistencies caused by partial failures
- Works with both relational and non-relational databases
Drawbacks
- Requires a complementary pattern (Polling Publisher or Transaction Log Tailing) to actually publish the messages
- Adds an OUTBOX table or message attribute that must be managed and cleaned up
- Polling from non-relational databases can be challenging due to the need to search across all records
When to Use
Apply Transactional Outbox when:
- A microservice must publish a message whenever it performs a database update (e.g., in Saga or CQRS)
- You need a guarantee that message publication and database updates either both succeed or both fail
Avoid when:
- The microservice does not publish messages — the pattern adds overhead that is unnecessary if there is no messaging requirement