Implementing idempotency in microservices

The Devprime platform offers automatic idempotency functionality for use in microservices.

We’ll implement an example in backend mode where you don’t need to pass a key to consume the microservice API. The process automatically manages the idempotency of the API payload.

The first step to enable idempotency is to modify the “Idempotency” setting in Idempotency in the “Devprime_App”. If you haven’t, you need to add a second State for idempotency to persist.

Parameters used in the configuration

  • Alias indicates the State used in the persistence of Idempotency
  • Duration is used to set the time of the command duplicate control record.
  • Flow indicates type of Idempotency and can be set to “backend” or “frontend”
  • Key is used to set a required key on the head in the Flow frontend
  • Scope limits the performance of the idepontence and uses the parameters “all|web|stream”
  • Action sets whether the ide will be automatic or manual with the parameters “auto|manual”

Creating a microservice to use in the example

We will use a microservice based on the Devprime platform

Starting the idempotency setup

Setting idempotency on the “Devprime_App” switch
Change in the Idempotency setting in the “Enabled” option to “true”
code src/app/appsettings.json

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "auto"
    }

Include a second persistence in the “Devprime_State” key
In this example, we’ll use a local Redis with a default password
code .\src\app\appsettings.json

1
2
3
4
5
6
7
8
9
{
  "enable": "true",
  "alias": "State2",
  "dbtype": "redis",
  "connection": "127.0.0.1:6379,password=LltF8Nx*yo",
  "timeout": "5",
  "retry": "2",
  "durationofbreak": "45"
}

Starting automatic idempotency in the microservice

Now it’s time to test the configuration. Before you start the microservice, make sure that you have enabled the containers and created the queue in RabbitMQ.

Run the application and post via the Order API
In the example below we are using a standard json for the post.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "customerName": "Bill",
  "customerTaxID": "string",
  "itens": [
    {
      "description": "short",
      "amount": 1,
      "sku": "XNY1AC",
      "price": 100
    }
  ],
  "total": 100
}

Note the idempotency information in the Log
The idempotency process automatically came in to secure this HTTP request without the need for any information from the API consumer side.
Devprime Capabilities idempotency

Make a second identical post via the Order API
By looking at this second scenario, it is already possible to see that idempotency protected the microservice by preventing a duplicate inclusion.

The API has already received a return rejecting the duplicate POST
Devprime Capabilities idempotency

By analyzing the Log we are able to follow the entire idempotency process
Devprime Capabilities idempotency

Initiating manual idempotency in the microservice

Devprime allows you to manually enter a specific method that will support idempotency. The first step is to change the main configuration and then go directly to the method to add the configuration.

Changing the “Action” key to “Manual”

1
2
3
4
5
6
7
8
9
    "Idempotency": {
      "Enable": "true",
      "Alias": "State2",
      "Duration": "86400",
      "Flow": "backend",
      "key": "idempotency-key",
      "Scope": "all",
      "Action": "manual"
    }

By using the “Action” option as “manual” if you run the microservice again and make a duplicate post, you will notice that it will not reject, because the automatic process is turned off.

Enabling Idempotency in a Method
Since the process is now manual, we will activate idempotency in each method to be protected. In the example below we demonstrate this possibility directly in the Web Adapter.
code src\Adapters\Web\Order.cs

Locate the “Order” API in the Web Adapter and make the modification as shown.

1
2
3
4
5
app.MapPost("/v1/order", async (HttpContext http, IOrderService Service, Devprime.Web.ViewModels.Order.Order command) => await Dp(http).Pipeline(() =>
        {
            Dp(http).Idempotency.Enable = true;
            Service.Add(command.ToApplication());
        }));

Run it again and you’ll notice that the idempotency feature has worked again, but only for POST in the “/v1/order” API.

Implementing idempotency in microservices
Idempotency in microservices and REST APIs

Last modified January 10, 2024 (967dcac3)