Skip to content
Mogens Heller Grabe edited this page May 25, 2017 · 5 revisions

Idempotence (which you may read a formal definition of on Wikipedia), when we are talking about messaging, is when a message re-delivery can be handled without ending up in an unintended state.

Since we always run the risk of processing the same message twice, it is a good idea to think a little bit about idempotence from time to time.

Please read the page about delivery guarantees if it is not clear at this point why we might process the same message twice.

So how do we deal with the risk of receiving the same message twice?

Naturally idempotent message processing

Generally, the best way to deal with message re-deliveries is to make the processing of each message naturally idempotent.

Natural idempotence arises when the processing of a message consists of calling an idempotent method on a domain object, like

obj.MarkAsDeleted();

or

obj.UpdatePeriod(message.NewPeriod);

or something like that, or if the processing of the message is of the upsert type, e.g. like

var itemRows = message.Items.Select(i => new ItemRow(i.Id, i.Name));

await debaser.Upsert(itemRows);

(in this case using the nifty Debaser library to do that, but some manually written SQL with appropriate unique constraints can do the trick too...)

You can come a long way, simply by making much of your message handler code idempotent like this.

Explicitly handling re-deliveries

Do not forget this!

When a message can be re-delivered, and it follows from the order of operations when handling a message that we are unsure whether any outgoing messages were sent, you must always ensure that outgoing sent and published messages are sent and published every time, even though the processing of a message can be identified as a re-delivery.

Clone this wiki locally