How do you guarantee at-least-once event delivery for a financial transaction?

Atomicity of state changes and side effects without 2PC.
Write events to a DB outbox in the same transaction as the biz update; a relay polls and publishes to analytics.
Suggesting direct HTTP POSTs or dual writes.
What's really being asked
This question probes your ability to guarantee atomicity between a local database transaction and an external side effect without using distributed transactions such as two-phase commit. The interviewer cares that you understand the dual-write problem, where a service crash or network partition can leave the database and analytics backend inconsistent.
The full answer
First, explain that the application must write the analytics event to an outbox table stored in the same database as the business data, using a single local transaction. Second, describe a separate message relay process that polls the outbox or tails the transaction log, publishes events to the analytics backend, and retries on failure until it receives an acknowledgment. Third, note that because the relay might crash after publishing but before deleting or marking the message as sent, the analytics consumer must be idempotent, typically by tracking processed event IDs. Fourth, mention that ordering is preserved because messages are read from the outbox in insertion order and published sequentially.
The mistakes people make
A red flag is suggesting a fire-and-forget HTTP POST from the application thread immediately after the database commits, because a process crash between commit and send loses the event forever. Another red flag is proposing a saga or 2PC across the database and the analytics backend, since most analytics systems do not support XA transactions and the coupling is undesirable. Simply using a message queue without the outbox also fails if the queue write is not atomic with the business transaction.
What usually comes next
The interviewer may ask how to implement the message relay, comparing polling publisher versus transaction log tailing. They might ask how to handle high throughput, which could lead to discussion of batching publishes or using a separate CDC stream like Debezium. They may also ask how to guarantee ordering across multiple service instances updating the same aggregate, or how to prune the outbox table once messages are confirmed sent.
A concrete example
Imagine a payment service processing a 500 dollar transfer. Inside the same PostgreSQL transaction that debits the sender and credits the receiver, the service inserts a row into an analytics_outbox table containing a JSON payload with the transaction ID, amount, and timestamp. A background worker queries the outbox every second, publishes each row to a Kafka topic, and updates the row status to SENT only after Kafka acknowledges the write. If the worker restarts, it resumes from the earliest unsent row, ensuring at-least-once delivery. The analytics service consumes the topic and drops duplicates by checking a processed_event_ids table keyed by the event ID.
Interview question
Which design ensures a payment database update and its analytics event are atomic without using distributed transactions?
- a.Publish the event to a message queue from the application thread immediately after the database write succeeds.
- b.Write the event to an outbox table in the same database transaction as the business update, then relay it to analytics.Correct
- c.Send an HTTP POST to analytics immediately after committing the database transaction.
- d.Use a two-phase commit between the payment database and the analytics backend.
Why? this is the answer
Writing the event to an outbox table in the same local database transaction atomically binds the state change to the event record, and a separate relay publishes to analytics. The HTTP POST distractor is unsafe because a crash between the database commit and the network call permanently loses the event.
Just read this? Test yourself on what you have been reading.
Read the original → microservices.io
- #transactional outbox
- #at-least-once delivery
- #analytics
- #microservices
- #data consistency
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.
See open roles