Let's understand the term "Indempotent" in general. Indempotent is something that keeps the same value when multiplied by itself, no matter how many times the function is applied.
With respect to an application, if the same operation is being performed multiple times, it will result in the same output except the first instant. Now, idempotent API means that if the same request is made a number of times, then it will have the same impact as making the request just once.
Idempotent APIs are characteristic for creating deoendable and liner web service when clients might attempt to send the same request multiple times due to network instability and protect your application from duplicate requests caused by network issues or even client-side mistakes.
Relating this concept to a real-time example, an elevator button is idempotent. No matter how many times you press the same elevator button, the elevator will make one trip to the designated floor. Your APIs should work the same way. That is, if a client submits the same request twice, the state of the server will be the same as if it only received that request once. This is even more relevant in distributed systems where the network can often be untrustworthy, and clients may need to retry their requests due to timeouts or other errors.
Idempotency is an essential concept in the HTTP protocol and is described by HTTP/1.1. It assists in making certain that operations can be easily redone without leading to unfavorable consequences or data damage. For instance, if a user tries to submit a form to update their profile and the request fails due to timeout, the client can submit the request again without affecting the database and creating multiple records.
Why do we need idempotent APIs?
Idempotent APIs ensure safe retrying requests without accidentally performing the same operation twice. When creating or updating an object, use an idempotency key. Then, if a connection error occurs, you can safely repeat the request without the risk of creating a second object or performing the update twice.
The HTTP methods GET, HEAD, OPTIONS, and TRACE are idempotent because they do not modify the state of a resource in the server. Instead, they fetch the relevant resource metadata or its representation. They are naturally idempotent since they do not change the server state of the resource.
Let us understand the importance of API idempotency with an example. In a typical shopping cart application, a user often needs to make an API call to create a new order. If the API request is successful, the user should get a confirmation. However, a network issue might prevent the user from receiving confirmation, even if the user made the API request. In this case, the user might want to recreate the same order, i.e., retry the same API call, because they did not receive a confirmation after the previous request to create a new order.
What if the same order is created more than once? Clearly, we want to avoid duplicating orders. You should design your shopping cart API to be idempotent to avoid creating duplicate orders when a user makes multiple retries to the same API endpoint.
Understand idempotency in HTTP methods
The HTTP POST and HTTP PATCH methods are not idempotent. However, the HTTP methods GET, HEAD, PUT, and DELETE are idempotent by design.
HTTP GET: Retrieves data from the resource without making any changes to its contents. In the GET method, if several requests are made for retrieving the same resource, then the result will be the same.
HTTP HEAD: GET, but unlike it, it only returns the headers. This is mostly used to query the metadata of a resource without the need to download the body of the content.
HTTP PUT: Inserts the contents of the request payload into the field of the target URL. Having the same resources in the request body and sending two PUT requests lead to the same resource state.
HTTP DELETE: Cancels the resource to be offered at the exact URL in question. The DELETE request repeated does not serve any purpose after the first deletion.
HTTP POST: The HTTP POST method is used to send data to the server for processing. Because a POST operation can create a new resource on the server, it is never idempotent. Multiple POST calls can result in multiple new resources.
HTTP PATCH: The HTTP PATCH method is used to modify a resource on the server without altering the entire resource. This method is not idempotent because repeated HTTP PATCH requests can change the state of the resource repeatedly.
Based on the above scenario, let's design a model class for an order section from the Shopping Cart project, and in addition to that, let's add an Idempotent key class to handle multiple POST requests while creating a new order everytime.
HTTP POST methods are not idempotent by design because they are used to process data or create new resources. However, we can make them idempotent by writing custom logic. The following sequence of steps illustrates the logic:
- The client creates a unique key with each request and sends it to the server in a custom header.
- When the server receives the request, it checks whether the key is new or already exists.
- If the key is new, the server processes the request and saves the result.
- If the key already exists, the server returns the result of the stored operation without processing the request again.
- In short, we assign a unique key to each request that allows the server to determine whether the request has already been processed. In this way, we ensure that each request is processed once and only once.
Create the model classes
![Create Model Classes]()
While the Product and Order classes are typically used in a ShoppingCart application, the KeyStore class is used here to store our idempotency keys. In this implementation, we’ll save these keys in the database (dbContext). Naturally, you could change the implementation to store the keys in the cache or any other data store.
Create the controller class
Right-click on the Controllers folder in the Solution Explorer Window and create an API controller called OrderController. Now, enter the following action method in the OrderController class. This method creates a new order.
![Controller class]()
Examine the code above. An idempotency key is generated on the client side and passed in the request header. This key will be used by the server to ensure that repeated calls to the same action method will not create duplicate records in the database. In other words, if the key is already present in the KeyStore, then the request for the creation of the resource will be ignored. The presence of the key in the KeyStore means that the request was already processed earlier.
Consider a positive scenario where we attempt to add an order using the above method and use the authenticate Key in the header to create an order.
![Header]()
Now, for another scenario, where you request the same api call again as you didn't get the response or order_Id on your first instant due to network failure or connectivity issue using the same Key and request body.
![Key and request body]()
If you observe, I have requested the same API call using the same key and request body, which may result in another order creation with the same details. To avoid this redundancy, we can verify a Key to process further with order creation action and revert back with valid responses for user reference and understandability. Here, we have achieved Idempotency with the POST method.
Takeaways
There is no doubt that the concept of Idempotent REST APIs is crucial when it comes to developing robust, efficient, and predictable web services. This is because by providing every repeated request with the same outcome as a single request, idempotent APIs supplement the system’s strength, make the client’s code less complicated, and enhance users’ satisfaction. Improving idempotency can help make your APIs better and more trusted since they can be part of distributed systems where network reliability cannot be guaranteed.