AWS Security ChangesHomeSearch

AWS powertools documentation change

Service: powertools · 2026-07-13 · Documentation low

File: powertools/typescript/latest/features/idempotency.md

Summary

Added documentation section 'Using multiple idempotent operations' explaining configuration requirements when using multiple persistence layers. Added links to Data Masking and Signer features. Updated example imports to use .js extensions. Changed date from 2026-05-27 to 2026-07-10.

Security assessment

The changes focus on operational guidance for idempotency configuration. No security vulnerabilities, exploits, or security incidents are mentioned. The persistence layer configuration changes prevent logical errors/stale results but don't address security flaws.

Diff

diff --git a/powertools/typescript/latest/features/idempotency.md b/powertools/typescript/latest/features/idempotency.md
index 3045f1b34..61480f16d 100644
--- a//powertools/typescript/latest/features/idempotency.md
+++ b//powertools/typescript/latest/features/idempotency.md
@@ -63,0 +64 @@ Event Handler
+          * Using multiple idempotent operations 
@@ -101,0 +103 @@ Event Handler
+      * [ Data Masking  ](../data-masking/)
@@ -102,0 +105 @@ Event Handler
+      * [ Signer  ](../signer/)
@@ -138,0 +142 @@ Table of contents
+    * Using multiple idempotent operations 
@@ -1683,0 +1688,180 @@ index.tsExample eventtypes.ts
+### Using multiple idempotent operations¶
+
+You can make multiple functions idempotent within the same Lambda function, each with its own configuration.
+
+In most cases, you can and should share the same persistence layer instance across idempotent operations. All the settings you pass when instantiating it - i.e. table name, attribute names, or a custom AWS SDK client - are safe to share.
+
+However, a persistence layer instance also carries the idempotency configuration of the **first operation that uses it** , and silently ignores subsequent ones.
+
+For this reason, operations that need different `IdempotencyConfig` settings - i.e. different `eventKeyJmesPath` expressions - must each use their own persistence layer instance. If they shared one, the second operation would extract the idempotency key using the first operation's expression, which can cause it to always resolve to the same key and return stale results.
+
+When using multiple persistence layer instances, you can still share the same AWS SDK client to reuse the underlying connection.
+
+index.tstypes.ts
+    
+    
+     1
+     2
+     3
+     4
+     5
+     6
+     7
+     8
+     9
+    10
+    11
+    12
+    13
+    14
+    15
+    16
+    17
+    18
+    19
+    20
+    21
+    22
+    23
+    24
+    25
+    26
+    27
+    28
+    29
+    30
+    31
+    32
+    33
+    34
+    35
+    36
+    37
+    38
+    39
+    40
+    41
+    42
+    43
+    44
+    45
+    46
+    47
+    48
+    49
+    50
+    51
+    52
+    53
+    54
+    55
+    56
+    57
+    58
+    59
+
+| 
+    
+    
+    import {
+      IdempotencyConfig,
+      makeIdempotent,
+    } from '@aws-lambda-powertools/idempotency';
+    import { DynamoDBPersistenceLayer } from '@aws-lambda-powertools/idempotency/dynamodb';
+    import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
+    import type { Context } from 'aws-lambda';
+    import type { Request, Response } from './types.js';
+    
+    // You can share the same AWS SDK client across persistence layer instances
+    const dynamoDBClient = new DynamoDBClient({});
+    
+    const processUser = makeIdempotent(
+      async (user: { userId: string }) => {
+        // ... process user
+        return { userId: user.userId };
+      },
+      {
+        // Operations with different configs need their own persistence layer instance
+        persistenceStore: new DynamoDBPersistenceLayer({
+          tableName: 'idempotencyTableName',
+          awsSdkV3Client: dynamoDBClient,
+        }),
+        config: new IdempotencyConfig({
+          eventKeyJmesPath: 'userId',
+        }),
+      }
+    );
+    
+    const processProduct = makeIdempotent(
+      async (product: { productId: string }) => {
+        // ... process product
+        return { productId: product.productId };
+      },
+      {
+        // Don't reuse the instance above: this operation has a different config
+        persistenceStore: new DynamoDBPersistenceLayer({
+          tableName: 'idempotencyTableName',
+          awsSdkV3Client: dynamoDBClient,
+        }),
+        config: new IdempotencyConfig({
+          eventKeyJmesPath: 'productId',
+        }),
+      }
+    );
+    
+    export const handler = async (
+      event: Request,
+      _context: Context
+    ): Promise<Response> => {
+      const user = await processUser({ userId: event.user });
+      const product = await processProduct({ productId: event.productId });
+    
+      return {
+        user,
+        product,
+        statusCode: 200,
+      };
+    };
+      
+  
+---|---  
+      
+    
+     1
+     2
+     3
+     4
+     5
+     6
+     7
+     8
+     9
+    10
+    11
+    12
+    13
+
+| 
+    
+    
+    export type Request = {
+      user: string;
+      productId: string;
+    };
+    
+    export type Response = {
+      [key: string]: unknown;
+    };
+    
+    export type SubscriptionResult = {
+      id: string;
+      productId: string;
+    };
+      
+  
+---|---  
+  
+Note
+
+The same applies to the `@idempotent` decorator and the `makeHandlerIdempotent` Middy middleware: operations with different idempotency configurations need their own persistence layer instance.
+
@@ -3859,2 +4043,2 @@ CustomPersistenceLayerindex.tstypes.ts
-    } from './advancedBringYourOwnPersistenceLayerProvider';
-    import type { ApiSecret, ProviderItem } from './types';
+    } from './advancedBringYourOwnPersistenceLayerProvider.js';
+    import type { ApiSecret, ProviderItem } from './types.js';
@@ -4047 +4231 @@ CustomPersistenceLayerindex.tstypes.ts
-    import { CustomPersistenceLayer } from './advancedBringYourOwnPersistenceLayer';