Why We Need Idempotency Mechanism

Once is enough…

Idempotency is a strategy that makes sure an event that executed multiple times will give the same result. For example, GET method on the HTTP request. If you calling the endpoint with GET method will give you the same result. But POST method is not idempotent because every time you call an endpoint with POST method will create a new record on the database (the database state changes).

When we need it?

Image this scenario. Our payment backend has an endpoint to add a new record on transactions table, which is it used POST method. Our frontend app — have retry mechanism — calls the endpoint to make a new transaction. Our backend receives the request, makes a new transaction, and reduce the user’s balance.

But somehow network failure happened and the frontend app does not receive the response. Because of the time limit, the frontend app retries to send the same request. Our backend receives the request, makes a new transaction, and reduce the user’s balance.

Do you know what actually happened? The user’s balance reduced twice. We don’t want our customer got angry because of this failure. How we can solve this problem?

Make request Idempotent

To make request idempotent, we need to create a unique identifier for each request. Every time the frontend app creates a new request, it will generate a unique identifier that will send to the backend. We can put it on the request header or the request body. I don’t know what is the best practice where to put it, but the point is our frontend will send a unique identifier for each request.

Every time backend receives a request from the frontend app, it will check if the request’s unique identifier exists or not. The backend should have a mechanism to store the unique identifier. Maybe we can use Redis to store it temporarily.

If the request’s unique identifier doesn’t exist — means it is a new request, the request will be processed. The unique identifier and response body of the request will be stored to our cache. If the request’s unique identifier exists — mean the request ever processed before, the backend will return the cached response body without process the request again.

This is one of the ways how we can achieve idempotency. I still don’t know if there another way to achieve idempotency. The idempotency very useful to make sure the one request — that make the state change — not executed multiple times.