Idempotence and exceptions

Guys, is there a best practice how to deduplicate commands that do not produce any events?

1. Message A is processed but doesn’t update an aggregate.
2. Message B is processed, and the message consumer updates the aggregate.
3. Message A is redelivered, and because there’s no record of it having been processed, the message consumer updates the aggregate.
4. Message B is processed again

In this scenario, the redelivery of events results in a different and possibly erroneous outcome.

This scenario is taken from “Microservices Patterns” book and the suggested solution is to always publish an event.

I think that I need to produce an event (with deterministic id), ‘OperationFailed’ in case of an exception thrown by the aggregate into its stream. In this way, EventStore’s deduplication by (stream, event id) will work.

However, what if I get an exception during aggregate creation and hence, I don’t have a stream yet?

For me, it boils down to the most important question that the Aggregate should answer- can and should I do it?

The Aggregate state can usually provide the answer for both. For example, if you try processing a payment twice, you already see that it’s been paid and the payment id is the same, so you can ignore it. It if’s paid with a different payment id - something went wrong and you make another decision.