Idempotency

Idempotence is a property of an operation (transaction) whereby they can be applied multiple times without changing the result beyond the initial application.

Wikipedia

ClientToken parameter

TransactWriteItems api has a parameter that can be used for making this API’s behavior idempotent. The name of the parameter is ClientToken.

Client Token is valid for 10 minutes i.e., the if token is re-used within 10 minutes the behavior of the TransactWriteItems will be idempotent but if the same token is used after 10 minutes, the token will be treated as a new token/transaction and the operations will be executed.

  1. The application can invoke the API with ClientToken set to some value lets say 12345.
  2. Lets say the call was received by the service and the n/w connection broke!!
  3. Application did not receive the response as the network connection broke
  4. Application retries the transacton with ClientToken=12345
  5. Service checks if the transaction with clienttoken 12345 has already been processed or not - since it was already processed no further action will be taken. A success response is sent to the application

As you can see wit th euse of ClientToken, TransactWriteItems API is behaving like an idempotent operation.

client-token-parameter

Example

  • This is for the Flash Sale scenario discussed earlier
  • The LoyaltyPoints for the customer must be updated in idempotent manner
  • The example below will ensure that LoyaltyPoints are updated ONLY once
aws dynamodb transact-write-items  \
    --client-request-token  12345,  \
    --transact-items '[
        { 
            "Update": {
                "TableName": "FlashSaleDiscounts",
                "Key": {
                    "PK": {"S":"CUST#john"}, 
                    "SK": {"S":"CUST#john"}
                },
                "UpdateExpression": "SET #LoyaltyPoints = #LoyaltyPoints + :LoyaltyPoints",
                "ExpressionAttributeNames": {"#LoyaltyPoints":"LoyaltyPoints"},
                "ExpressionAttributeValues": {":LoyaltyPoints": {"N":"500"}}
            }
        }
    ]'   \
    --endpoint-url http://localhost:8000