Intro
A few days ago, I had an unfortunate experience wiring money to a friend using a popular app. Here’s what happened:
I initiated the payment process.
After completing it, I saw a generic error: “Something went wrong.”
I repeated the process.
This time, it was completed successfully.
Checking my transactions, I saw two successful transactions, meaning I wired double the intended amount.
Luckily, my friend was kind enough to return half the amount. This could lead to customer complaints, churn, and disappointment in other cases. Let’s see how idempotency could have helped in this case.
Example
Imagine you’re organizing an event and delegating tasks to your team. Let’s explore a few versions of the same instruction.
Version 1
“Please order some flowers.”
While straightforward, this instruction lacks information on who should do it, when, and its status. One team member might start working on it, and a few minutes later, another might do the same, causing duplicated work.
Version 2
“Please order some flowers for the company event by tomorrow.”
This version gives more context but still lacks acknowledgment and duplication handling.
Version 3
“Alex, please order some flowers for the company event by tomorrow, and react with a ‘thumbs-up’ once done.”
“Please order some flowers for the company event by tomorrow, acknowledge this message when you start working on it, and ensure no one else has already done it.”
These versions assume the message can be read multiple times by multiple people and suggest tactics to avoid duplication.
Idempotency
Idempotency ensures no unintended side effects from repeated actions. It has two main aspects:
Handling Lost Instructions: If the original message is lost, sending it again ensures the task is understood and executed correctly. A unique key ensures that resending the event doesn't lead to redundant actions.
Handling Multiple Instructions: If a message is sent multiple times, the receiver will recognize the unique key and act on it only once. This prevents duplicated efforts and ensures consistent execution.
Let’s return to my case with the duplicated payment. Considering idempotency, we can define these rules:
Users can make one transaction every 5 seconds (otherwise, show a warning).
Users cannot transact with the same recipient and amount within less than 2 minutes.
If a duplicated transaction is recognized, block it and show a proper message to the user.
Users can still override the duplication decision and proceed with the transaction.
These rules complicate the technical design and business logic but improve the user experience and make the system more resilient. This is especially important in an event-driven architecture.
Conclusion
Idempotency ensures reliable and consistent outcomes in technical systems and everyday scenarios. Addressing the above can prevent unintended side effects such as duplicated efforts or missed tasks.
Applying these principles improves user experience and enhances system resilience, making them vital considerations in large-scale systems.