Wait… before you start reading… get this – it is a very important topic.
Maybe you are someone who already knows about idempotence or someone who is hearing this word for the first time. This article is going to help you all in some way or the other.
I’m a backend engineer. No that’s not right… I’m a full-stack developer specialised in backend development. Yeah, that’s close enough. The point is I’ve always known about the concept of idempotence but I never realised its importance until a few weeks ago when something bad happened.
That’s why I said at the start – Idempotence is very important in backend applications/services.
Table of Contents
What is Idempotenct?
Let’s start with a simple dictionary definition and from there will see what it means when writing backend services.
From the above definition, any element is unchanged in value even after multiple operations. In mathematics, an idempotent operation is one where f(f(x)) = f(x). For example, the abs()
function is idempotent because abs(abs(x)) = abs(x)
for all x
.
Let me make it functional.
Try the below example (enter 1, 2 or 3 and press discard multiple times)
- Item 1
- Item 2
- Item 3
No matter how many times you press that discard button, the state of the list will change once... on the first operation. The result will be unchanged no matter how many times you press the discard button. This is a very short but complete example of idempotence.
What do we mean by Idempotent in HTTP methods?
I think now definitions will start to make more sense.
Here's one in regards to HTTP methods.
An HTTP method is idempotent if an identical request can be made once or several times in a row with the same effect while leaving the server in the same state. In other words, an idempotent method should not have any side effects (except for keeping statistics). Implemented correctly, the GET
, HEAD
, PUT
, and DELETE
methods are idempotent, but not the POST
method. All safe methods are also idempotent.
You see I have underlined, bold and colored the word Implemented Correctly in the above definition. Let's say some really smart developers used the DELETE method in a way that it deletes the last entry from the table. Then this is not idempotent... because now... with every delete call, it will delete the last entry from the table. That means every DELETE request is changing the state of the system. Therefore, it's not implemented correctly.
Wait!!! I can quickly demonstrate this behaviour.
Here,
- Item 1
- Item 2
- Item 3
So as long as the methods are implemented safely, the GET
, HEAD
, PUT
, and DELETE
methods are idempotent.
In case you want to read some more in detail, here's a good resource,
Why Is Idempotence Important?
Coming to the meaty part now. After all, why is this so important that I decided to write this article in the middle of the night. One reason is I cannot sleep and the other is that you might lose sleep (and money) if you are working on critical applications that directly result in revenue for the company.
Let's take a simple real-world example. Suppose you are a customer who took some loan from ME. Now let's say I have a service that talks to some other service that does the interest calculation for ME (because I'm lame with calculations :p). The setup would look somewhat like this,
At this point, if there is some communication delay, I will send the message again and the interest will be accrued twice for the same day. And you will sue me at the end and I will lose a fortune.
In this case, the third person is not idempotent. Because every message is changing the state of the system.
So, to avoid the recalculation or charging YOU twice, I can make this service (another person) idempotent by asking him to check the message before doing the calculation.
Now... this is important. You should be very careful in choosing the right key attribute that will always be the same for the given message.
In this example - I don't want to accrue interest twice for the same person (YOU) more than once for the same day. So the key attributes will be -
- User Id
- Date
So, If I'm sending a message with the same user id and on the same date twice then the third person will discard the following messages.
This is the benefit of idempotence.
This can save my company from getting sued over a small issue :p 😀
Illustration
In the below example, think of the number as the interest accrued. And the increment button is ME telling the calculator guy to accrue interest.
In the non-idempotent solution, the number will increment every time you hit that button.
In the idempotent solution, it will only increment once per minute. (Think of minute as a day to relate with the above example)
Non idempotent example
You can hit the increment button N times and every time it will increment the number. But that is not the case with example 2.
Example 1
1
Idempotent by minute
You can only increment the number after each minute.
You can imagine a minute as a day for a reference. So the number will only increment once for a given minute. Wait for another minute. So, no matter how many times you press the button, it will only increment once in a minute.
This is the best I can do in a short time to illustrate idempotence.
Example 2 - Idempotent by Minute
1
Take Away
The one takeaway that I want you from this article is that - Do give a lot of thought before writing a service or REST API that will change the state of your system. Especially if it is going to have a financial consequence.
This is something even experienced developers overlook and sometimes the price is really huge.
I'm one of the lucky few who have seen a considerable impact that could have been avoided if the idempotence key would have been chosen thoughtfully. And this happens.
I hope you enjoyed the article.
If you liked the article then do something through which I would know that you liked it. The easier way is to comment below 🙂
Till next time.