IDEMPOTENCY

One Serverless Principle to Rule Them All

Moar Serverless!!! 2022

@AdrienneTacke

@AdrienneTacke

IDEMPOTENCY

-- One Serverless Principle to Rule Them All

Agenda

idempotency

Not a real word,

according to Merriam-Webster.

idempotent

idem·​po·​tent : relating to or being a mathematical quantity which when applied to itself under a given binary operation equals itself

Merriam-Webster

idempotent

i·​dem·​po·​tent : unchanged when multiplied by itself

Random House Webster's

idempotency

i·​dem·​po·​ten·cy : characteristic that ensures when running an operation over and over, and given the same input, that the same output is achieved every single time.

Adrienne and other developers

"...when multiplied by itself"

"unchanged"

Great, what does

                          have to do with good serverless architecture?

– Curious Moar Serverless Attendee

Have you heard about the seven design principles of well-architected applications?

– Me, Adrienne

seven design principles of well-architected applications*

* Source: https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/general-design-principles.html

🧱  Speedy, simple, singular

🔀  Think concurrent requests, not total requests

🙅🏻‍♀️   Share Nothing

💽  Assume no hardware affinity

 🚦   Orchestrate your application with state machines, not functions

📨  Use events to trigger transactions

☔   Design for failures and Duplicates

seven design principles of well-architected applications*

* Source: https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/general-design-principles.html

🧱  Speedy, simple, singular

🔀  Think concurrent requests, not total requests

🙅🏻‍♀️   Share Nothing

💽  Assume no hardware affinity

 🚦   Orchestrate your application with state machines, not functions

📨  Use events to trigger transactions

☔   Design for failures and Duplicates

Impossible without idempotency!

☔   Design for failures and Duplicates

Failures

retries

lead to

.

retries

means

duplicates

can and will occur.

Implementing

Failures

lead to

.

retries

duplicates

If

exist,

is key to mitigate side effects.

idempotency

retries

means

can and will occur.

Implementing

Failures

lead to

.

retries

duplicates

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

side effects

What happens without idempotency?

Order 🍰

Order placed

Order processed

Adrienne

Adrienne

Website

Website

API

API

What happens without idempotency?

Adrienne enters tunnel

Adrienne exits tunnel

Network failure

Time

Adrienne

Adrienne

Website

Website

API

API

Adrienne exits tunnel

Network failure

What happens without idempotency?

Time

Adrienne

Adrienne

Website

Website

API

API

Adrienne exits tunnel

Adrienne sees error and resubmits order

Order 🍰

Order placed

Order processed

🚚 Cake is on the way!

What happens without idempotency?

Time

Order 🍰

Order placed

Order processed

🚚 Cake is on the way!

Adrienne

Adrienne

Website

Website

API

API

What happens without idempotency?

Adrienne sees error and resubmits order

Network failure

Order 🍰

Order placed

Order processed

Adrienne enters tunnel

Adrienne exits tunnel

🚚 Also, this first cake is on the way!

Time

Surprise!

Order 🍰

Order placed

Order processed

🚚 Cake is on the way!

Adrienne

Adrienne

Website

Website

API

API

What happens without idempotency?

Adrienne sees error and resubmits order

Network failure

Order 🍰

Order placed

Order processed

Adrienne enters tunnel

Adrienne exits tunnel

🚚 Also, this first cake is on the way!

Time

Surprise!

side effect:

duplicate requests are considered valid requests

How do we apply idempotency?

How do we apply idempotency?

elements of idempotency

idempotency key

Generated by caller, unique identifier, captures intent

How do we apply idempotency?

idempotency key

idempotency layer

Generated by caller, unique identifier, captures intent

Acts like a filter,  decides what to do with a request

elements of idempotency

How do we apply idempotency?

idempotency key

idempotency layer

persistent storage

Generated by caller, unique identifier, captures intent

Acts like a filter,  decides what to do with a request

Stores state, "source of truth" for idempotency keys, list of checkpoints in retries

elements of idempotency

How do we apply idempotency?

idempotency key

idempotency layer

persistent storage

Stores state, "source of truth" for idempotency keys, list of checkpoints in retries

Acts like a filter,  decides what to do with a request

Generated by caller, unique identifier, captures intent

elements of idempotency

How do we apply idempotency?

Generate unique identifier

Adrienne

placeOrder(event) {
  const context = event.context;
  const message = event.data;
  const order = {
    id: context.eventId,
    timestamp: context.timestamp,
    cake: message.data 
    	? Buffer.from(message.data, 'base64').toString() 
    	: '',
    idempotencyKey: "cb3d3141-a229-6ce0-b005-eb832e2cdabc"
  };
  
  // Remaining request logic
}

"cb3d3141-a229-6ce0-b005-eb832e2cdabc"

placeOrder(event)

How do we apply idempotency?

Adrienne

placeOrder(event)

API

Persistent Store

Run placeOrder handler(event)

Initial Request

Get idempotency key (event)?

Nothing found

Set idempotency key + handler result

Response not received by client

How do we apply idempotency?

Adrienne

placeOrder(event)

API

Persistent Store

Run placeOrder handler(event)

Initial Request

Get idempotency key (event)?

Nothing found

Set idempotency key + handler result

Response not received by client

Subsequent requests
(retries)

Get idempotency key (event)?

Exists: return result from initial request

Response sent to client

placeOrder(event)

Idempotency libraries and tools

Idempotency libraries and tools

✨ Features

  • Prevent multiple Lambda handler function executions on the same payload during a time window.
  • Reuse the same DynamoDB table to store idempotency state. Function name is added in addition to the idempotency key as a hash key.
  • Set expiration period for idempotency records.
  • Ensure Lambda handler returns the same result when called with the same payload.

Java, Python

# Idempotent decorator
from aws_lambda_powertools.utilities.idempotency import (
    DynamoDBPersistenceLayer, idempotent
)

persistence_layer = DynamoDBPersistenceLayer(table_name="IdempotencyTable")

@idempotent(persistence_store=persistence_layer)
def handler(event, context):
    payment = create_subscription_payment(
        user=event['user'],
        product=event['product_id']
    )
    ...
    return {
        "payment_id": payment.id,
        "message": "success",
        "statusCode": 200,
    }

🔑 Idempotency Key

hash representation of entire event or specific configured subset of the event

💾 Persistent Storage

Amazon DynamoDB (only supported persistent storage layer for now)

Other great tools and libraries!

Stripe API - Supports idempotent requests and implements idempotency keys.

https://stripe.com/blog/idempotency

IdempotentAPI - Performs additional idempotency checks. NuGet package.

https://www.nuget.org/packages/IdempotentAPI

https://stripe.com/docs/api/idempotent_requests

Step Functions - Serverless orchestration service.

https://docs.aws.amazon.com/step-functions

https://www.dotnetnakama.com/blog/idempotency-for-fault-tolerant-web-apis

Durable Functions - Azure's serverless orchestration service.

https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview

IDEMPOTENCY

One Serverless Principle to Rule Them All

@AdrienneTacke

Thank you Moar Serverless!!!