backenddrills

Messaging and replay

Handling duplicate Kafka messages without duplicate business effects

By the BackendDrills editorial team · Published and checked October 6, 2026 · 7-minute read

Before you start: Transactions, operation identity and retries. Find this reading in a study path →

An idempotent Kafka producer does not automatically make a consumer's external business effects happen once. A consumer can commit an external write and crash before committing its offset, then receive the record again. Protect the effect at the system that owns it.

Write down the failure window

Imagine a warehouse projection that increments a received quantity. A worker saves the increment, then restarts before its offset commit. The record returns after reassignment. If the handler increments again, the business result is wrong even though Kafka is functioning as designed.

Illustrative sequence:
1. Read event receiving-confirmed, event_id=receipt-42
2. Commit warehouse quantity update
3. Process stops before offset commit
4. Another worker receives receipt-42
5. The handler must recognize that its effect already committed

Committing the offset before the database write creates the opposite problem: a crash can skip an unapplied effect. Decide whether replay is acceptable and where durable evidence of completion belongs before choosing the commit order.

Make deduplication and the effect atomic

For this example, use a durable event identity and a unique constraint scoped to the relevant tenant and operation. Insert the receipt and apply the quantity update within the same database transaction. Only after it commits should the consumer acknowledge progress. If an identical receipt already exists, confirm that it represents the same business event and acknowledge the replay without repeating the increment.

Illustrative transaction, not executable SQL:
BEGIN
  insert receipt(tenant_id, event_id) under a unique constraint
  if the receipt was newly inserted:
      apply the warehouse quantity change
COMMIT
then commit consumer progress

The example assumes the receipt and quantity are in the same transactional database. A check followed by a separate insert is vulnerable to concurrent workers. A receipt committed separately from the effect can also claim success for work that never finished.

Know where Kafka transactions apply

Kafka transactions can coordinate consumed offsets with output records in Kafka. External destinations need their own cooperation. For a payment API or email delivery, examine the destination's idempotency contract, retention period and failure responses. An outbox can record intent atomically with a database change; it still needs a safe delivery and replay strategy.

Test more than a normal retry

TestRequired outcome for this example
Replay after the database commitQuantity changes once
Crash before transaction commitNo receipt without its effect
Two workers process the same identityThe unique constraint prevents a double effect
Same identity, different payloadMismatch is investigated, not silently discarded

Document how long event identities are retained and how historical replay works after that window. Monitor duplicate receipts and mismatches separately. A successful replay test demonstrates the stated warehouse invariant; it does not prove every downstream operation has exactly-once behavior.

Check the underlying behavior

Original illustrative examples, prepared with AI assistance and checked against the linked primary documentation. No customer incident or vendor endorsement is claimed. Our editorial approach.

Practice the next decision

Try a complete free backend drill: inspect evidence, make three decisions and review the reasoning. No account or card required.

Try a free incident drill →

Explore 1008 scenarios · $28 one-time

Selected practice from the study paths

Free readings need no account. Full edition drills require verified access; opening a paid link does not expose its answers.

Recommended next readings