
Error Handling
Part of Idempotency and duplicate prevention
Distinguishing repeated events from legitimate new actions
Tell redelivered events from genuinely new actions using both event identity and the identity of the business effect.
A repeated event and a new action can look similar. Use a stable event ID to identify redelivery, then use the business action's identity to decide whether a different event should create another effect. Rejecting everything with the same customer or payload would block legitimate work.
Ask two separate questions
First: have we seen this exact event before? A producer-issued event ID can answer that when it is stable across retries.
Second: has this business effect already been performed? Two different events might both request the same invoice or account update.
The first check protects against redelivery; the second protects the outcome.
For example, an order-approved event is delivered twice. Both deliveries should point to one invoice request. Later, a customer places another order for the same amount. That new order needs its own invoice.
A key based on customer ID and amount would make the wrong distinction. An order-specific identity separates the actions. This is a hypothetical design example.
Distinguishing Repeated Events vs. Legitimate New Actions
- Event Identity
- Stable event ID (e.g., producer-issued) to detect redelivery
- Business Effect Identity
- Unique key based on business context (e.g., customer ID + order ID)
- Outcome of Duplicate Event
- Skip or return prior result (no new effect)
- Outcome of Same Business Effect
- Check if already performed; prevent duplicate actions
- Outcome of New Action
- Allow new effect if business identity differs
Map the lifecycle
Write down which events can lead to each effect, including manual actions and corrections. Then specify when an effect is allowed again.
A reminder message might be sent once per appointment date, while a cancellation and rebooking could justify a new message. An “ever sent” flag is too broad if the underlying business state can legitimately change.
Incoming case / Typical decision to define
- Same event ID delivered again
- Return or skip the prior outcome
- New event ID requesting the same business effect
- Check whether that effect already exists
- New business action with similar fields
- Permit a new effect
- Same key carrying different meaning
- Stop and investigate a conflict
This decision table is an editorial model. The actual rule must follow the product's lifecycle and the producer's ID guarantees.
Lifecycle Decision Flow for Event Processing
- Check event IDIf previously seen → skip or return prior outcome
- Check business effect keyIf same effect exists → block duplicate action
- Evaluate new business actionIf different action → allow new effect
- Investigate conflicting keysSame key with different meaning → investigate conflict
Keep the evidence of the decision
Store the event ID, business key, effect ID and status together where operators can inspect them. A duplicate decision should be explainable: “event 53 was previously handled as invoice 91” is more useful than a silent discard.
Retention matters too. If old keys expire while retries are still possible, an old event may be treated as new.
Queue and event systems can deliver a message more than once. Azure and AWS both advise consumers to handle repeated processing safely. That does not mean every similar message is a duplicate.
Test one exact redelivery, one different event asking for the same effect, and one genuinely new action. The correct outcomes should be written down before the test so the deduplication rule does not simply encode the first implementation's behaviour.
Key Checks for Safe Event Deduplication
- Store event ID, business key, effect ID and status togetherFor auditability and debugging
- Test redelivery of same eventEnsure it is handled as prior outcome
- Test different event requesting same effectEnsure duplicate effect is blocked
- Test genuinely new actionEnsure new effect is permitted
- Retain decision evidence long enoughUntil all retries are complete
![How to choose the right idempotency key for an event: Keep the same idempotency key for retries of one action; use a new key for a new action.; Write: one [effect] for each [identity], e.g. one standard invoice per approved order.; Check stability, uniqueness, scope and lifetime; include tenant ID for tenant-scoped IDs. Choosing an idempotency key for an event](/covers/choosing-an-idempotency-key-for-an-event-640.webp?v=39704930)


