AWS Security ChangesHomeSearch

AWS lambda documentation change

Service: lambda · 2026-04-25 · Documentation low

File: lambda/latest/dg/durable-best-practices.md

Summary

Completely restructured the durable functions best practices documentation, removing detailed technical guidance on deterministic code, idempotency, state management, and step design, and replacing it with a high-level overview pointing to external SDK documentation and focusing on deployment, monitoring, and related resources.

Security assessment

This is a major documentation restructuring that removes extensive technical content about durable function programming patterns and replaces it with references to external documentation. There is no evidence of security vulnerability fixes, security incident documentation, or new security features. The change appears to be organizational - moving detailed technical guidance to the SDK documentation while keeping deployment and operational guidance in the Lambda documentation.

Diff

diff --git a/lambda/latest/dg/durable-best-practices.md b/lambda/latest/dg/durable-best-practices.md
index 38452befe..475ac28a3 100644
--- a//lambda/latest/dg/durable-best-practices.md
+++ b//lambda/latest/dg/durable-best-practices.md
@@ -7 +7 @@
-Write deterministic codeDesign for idempotencyManage state efficientlyDesign effective stepsUse wait operations efficientlyAdditional considerationsAdditional resources
+Function versions and aliasesMonitoringRelated resources
@@ -11 +11 @@ Write deterministic codeDesign for idempotencyManage state efficientlyDesign eff
-Durable functions use a replay-based execution model that requires different patterns than traditional Lambda functions. Follow these best practices to build reliable, cost-effective workflows.
+Durable functions use a replay-based execution model that requires different programming practices than traditional Lambda functions. See [Best practices](https://docs.aws.amazon.com/durable-execution/patterns/best-practices/) in the AWS Durable Execution SDK Developer Guide for guidance on how to write and test durable workflow code.
@@ -13 +13 @@ Durable functions use a replay-based execution model that requires different pat
-## Write deterministic code
+The following recommendations are best practices for deploying, invoking, and monitoring Lambda durable functions.
@@ -15 +15 @@ Durable functions use a replay-based execution model that requires different pat
-During replay, your function runs from the beginning and must follow the same execution path as the original run. Code outside durable operations must be deterministic, producing the same results given the same inputs.
+## Function versions and aliases
@@ -17 +17 @@ During replay, your function runs from the beginning and must follow the same ex
-**Wrap non-deterministic operations in steps:**
+Invoke functions with version numbers or aliases to pin executions to specific code versions. Ensure new code versions can handle state from older versions. Don't rename steps or change their behavior in ways that break replay.
@@ -19 +19 @@ During replay, your function runs from the beginning and must follow the same ex
-  * Random number generation and UUIDs
+## Monitoring
@@ -21 +21 @@ During replay, your function runs from the beginning and must follow the same ex
-  * Current time or timestamps
+Enable structured logging with execution IDs and step names. Set up CloudWatch alarms for error rates and execution duration. Use tracing to identify bottlenecks. For detailed guidance, see [Monitoring and debugging](./durable-monitoring.html).
@@ -23 +23 @@ During replay, your function runs from the beginning and must follow the same ex
-  * External API calls and database queries
+## Related resources
@@ -25 +25 @@ During replay, your function runs from the beginning and must follow the same ex
-  * File system operations
+  * [AWS Durable Execution SDK Developer Guide](https://docs.aws.amazon.com/durable-execution/)
@@ -26,0 +27 @@ During replay, your function runs from the beginning and must follow the same ex
+  * [Monitoring Lambda durable functions](./durable-monitoring.html)
@@ -27,0 +29 @@ During replay, your function runs from the beginning and must follow the same ex
+  * [Retries for Lambda durable functions](./durable-execution-sdk-retries.html)
@@ -29,390 +31 @@ During replay, your function runs from the beginning and must follow the same ex
-
-TypeScript
-    
-    
-    
-    import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
-    import { randomUUID } from 'crypto';
-    
-    export const handler = withDurableExecution(
-      async (event: any, context: DurableContext) => {
-        // Generate transaction ID inside a step
-        const transactionId = await context.step('generate-transaction-id', async () => {
-          return randomUUID();
-        });
-        
-        // Use the same ID throughout execution, even during replay
-        const payment = await context.step('process-payment', async () => {
-          return processPayment(event.amount, transactionId);
-        });
-        
-        return { statusCode: 200, transactionId, payment };
-      }
-    );
-              
-
-Python
-    
-    
-    
-    from aws_durable_execution_sdk_python import durable_execution, DurableContext
-    import uuid
-    
-    @durable_execution
-    def handler(event, context: DurableContext):
-        # Generate transaction ID inside a step
-        transaction_id = context.step(
-            lambda _: str(uuid.uuid4()),
-            name='generate-transaction-id'
-        )
-        
-        # Use the same ID throughout execution, even during replay
-        payment = context.step(
-            lambda _: process_payment(event['amount'], transaction_id),
-            name='process-payment'
-        )
-        
-        return {'statusCode': 200, 'transactionId': transaction_id, 'payment': payment}
-              
-
-###### Important
-
-Don't use global variables or closures to share state between steps. Pass data through return values. Global state breaks during replay because steps return cached results but global variables reset.
-
-**Avoid closure mutations:** Variables captured in closures can lose mutations during replay. Steps return cached results, but variable updates outside the step aren't replayed.
-
-TypeScript
-    
-    
-    
-    // ❌ WRONG: Mutations lost on replay
-    export const handler = withDurableExecution(async (event, context) => {
-      let total = 0;
-      
-      for (const item of items) {
-        await context.step(async () => {
-          total += item.price; // ⚠️ Mutation lost on replay!
-          return saveItem(item);
-        });
-      }
-      
-      return { total }; // Inconsistent value!
-    });
-    
-    // ✅ CORRECT: Accumulate with return values
-    export const handler = withDurableExecution(async (event, context) => {
-      let total = 0;
-      
-      for (const item of items) {
-        total = await context.step(async () => {
-          const newTotal = total + item.price;
-          await saveItem(item);
-          return newTotal; // Return updated value
-        });
-      }
-      
-      return { total }; // Consistent!
-    });
-    
-    // ✅ EVEN BETTER: Use map for parallel processing
-    export const handler = withDurableExecution(async (event, context) => {
-      const results = await context.map(
-        items,
-        async (ctx, item) => {
-          await ctx.step(async () => saveItem(item));
-          return item.price;
-        }
-      );
-      
-      const total = results.getResults().reduce((sum, price) => sum + price, 0);
-      return { total };
-    });
-              
-
-Python
-    
-    
-    
-    # ❌ WRONG: Mutations lost on replay
-    @durable_execution
-    def handler(event, context: DurableContext):
-        total = 0
-        
-        for item in items:
-            context.step(
-                lambda _: save_item_and_mutate(item, total),  # ⚠️ Mutation lost on replay!
-                name=f'save-item-{item["id"]}'
-            )
-        
-        return {'total': total}  # Inconsistent value!
-    
-    # ✅ CORRECT: Accumulate with return values
-    @durable_execution
-    def handler(event, context: DurableContext):
-        total = 0
-        
-        for item in items:
-            total = context.step(
-                lambda _: save_item_and_return_total(item, total),
-                name=f'save-item-{item["id"]}'
-            )
-        
-        return {'total': total}  # Consistent!
-    
-    # ✅ EVEN BETTER: Use map for parallel processing
-    @durable_execution
-    def handler(event, context: DurableContext):
-        def process_item(ctx, item):
-            ctx.step(lambda _: save_item(item))
-            return item['price']
-        
-        results = context.map(items, process_item)
-        total = sum(results.get_results())
-        
-        return {'total': total}
-              
-
-## Design for idempotency
-
-Operations may execute multiple times due to retries or replay. Non-idempotent operations cause duplicate side effects like charging customers twice or sending multiple emails.
-
-**Use idempotency tokens:** Generate tokens inside steps and include them with external API calls to prevent duplicate operations.
-
-TypeScript
-    
-    
-    
-    import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
-    
-    export const handler = withDurableExecution(
-      async (event: any, context: DurableContext) => {
-        // Generate idempotency token once
-        const idempotencyToken = await context.step('generate-idempotency-token', async () => {
-          return crypto.randomUUID();
-        });