AWS Lambda durable functions
Build resilient multi-step applications and AI workflows that can execute for up to 1 year while maintaining reliable progress despite interruptions.
Onboarding
Step 1: Validate Prerequisites
Before using AWS Lambda durable functions, verify:
AWS CLI is installed (2.33.22 or higher) and configured:
aws --version
aws sts get-caller-identity
Runtime environment is ready:
- For TypeScript/JavaScript: Node.js 22+ (
node --version)
- For Python: Python 3.11+ (
python --version. Note that currently only Lambda runtime environments 3.13+ come with the Durable Execution SDK pre-installed. 3.11 is the min supported Python version by the Durable SDK itself, however, you could use OCI to bring your own container image with your own Python runtime + Durable SDK.)
Deployment capability exists (one of):
- AWS SAM CLI (
sam --version) 1.153.1 or higher
- AWS CDK (
cdk --version) v2.237.1 or higher
- Direct Lambda deployment access
Step 2: Select language and IaC framework
Language Selection
Default: TypeScript
Override syntax:
- "use Python" → Generate Python code
- "use JavaScript" → Generate JavaScript code
When not specified, ALWAYS use TypeScript
IaC framework selection
Default: CDK
Override syntax:
- "use CloudFormation" → Generate YAML templates
- "use SAM" → Generate YAML templates
When not specified, ALWAYS use CDK
Error Scenarios
Unsupported Language
- List detected language
- State: "Durable Execution SDK is not yet available for [framework]"
- Suggest supported languages as alternatives
Unsupported IaC Framework
- List detected framework
- State: "[framework] might not support Lambda durable functions yet"
- Suggest supported frameworks as alternatives
Serverless MCP Server Unavailable
- Inform user: "AWS Serverless MCP not responding"
- Ask: "Proceed without MCP support?"
- DO NOT continue without user confirmation
Step 3: Install SDK
For TypeScript/JavaScript:
npm install @aws/durable-execution-sdk-js
npm install --save-dev @aws/durable-execution-sdk-js-testing
For Python:
pip install aws-durable-execution-sdk-python
pip install aws-durable-execution-sdk-python-testing
When to Load Reference Files
Load the appropriate reference file based on what the user is working on:
- Getting started, basic setup, example, ESLint, or Jest setup -> see getting-started.md
- Understanding replay model, determinism, or non-deterministic errors -> see replay-model-rules.md
- Creating steps, atomic operations, or retry logic -> see step-operations.md
- Waiting, delays, callbacks, external systems, or polling -> see wait-operations.md
- Parallel execution, map operations, batch processing, or concurrency -> see concurrent-operations.md
- Error handling, retry strategies, saga pattern, or compensating transactions -> see error-handling.md
- Advanced error handling, timeout handling, circuit breakers, or conditional retries -> see advanced-error-handling.md
- Testing, local testing, cloud testing, test runner, or flaky tests -> see testing-patterns.md
- Deployment, CloudFormation, CDK, SAM, log groups, deploy, or infrastructure -> see deployment-iac.md
- Advanced patterns, GenAI agents, completion policies, step semantics, or custom serialization -> see advanced-patterns.md
- troubleshooting, stuck execution, failed execution, debug execution ID, or execution history -> see troubleshooting-executions.md
Quick Reference
Basic Handler Pattern
TypeScript:
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
export const handler = withDurableExecution(async (event, context: DurableContext) => {
const result = await context.step('process', async () => processData(event));
return result;
});
Python:
from aws_durable_execution_sdk_python import durable_execution, DurableContext
@durable_execution
def handler(event: dict, context: DurableContext) -> dict:
result = context.step(lambda _: process_data(event), name='process')
return result
Critical Rules
- All non-deterministic code MUST be in steps (Date.now, Math.random, API calls)
- Cannot nest durable operations - use
runInChildContext to group operations
- Closure mutations are lost on replay - return values from steps
- Side effects outside steps repeat - use
context.logger (replay-aware)
Python API Differences
The Python SDK differs from TypeScript in several key areas:
- Steps: Use
@durable_step decorator + context.step(my_step(args)), or inline context.step(lambda _: ..., name='...'). Prefer the decorator for automatic step naming.
- Wait:
context.wait(duration=Duration.from_seconds(n), name='...')
- Exceptions:
ExecutionError (permanent), InvocationError (transient), CallbackError (callback failures)
- Testing: Use
DurableFunctionTestRunner class directly - instantiate with handler, use context manager, call run(input=...)
Invocation Requirements
Durable functions require qualified ARNs (version, alias, or $LATEST):
# Valid
aws lambda invoke --function-name my-function:1 output.json
aws lambda invoke --function-name my-function:prod output.json
# Invalid - will fail
aws lambda invoke --function-name my-function output.json
IAM Permissions
Your Lambda execution role MUST have the AWSLambdaBasicDurableExecutionRolePolicy managed policy attached. This includes:
lambda:CheckpointDurableExecution - Persist execution state
lambda:GetDurableExecutionState - Retrieve execution state
- CloudWatch Logs permissions
Additional permissions needed for:
- Durable invokes:
lambda:InvokeFunction on target function ARNs
- External callbacks: Systems need
lambda:SendDurableExecutionCallbackSuccess and lambda:SendDurableExecutionCallbackFailure
Validation Guidelines
When writing or reviewing durable function code, ALWAYS check for these replay model violations:
- Non-deterministic code outside steps:
Date.now(), Math.random(), UUID generation, API calls, database queries must all be inside steps
- Nested durable operations in step functions: Cannot call
context.step(), context.wait(), or context.invoke() inside a step function — use context.runInChildContext() instead
- Closure mutations that won't persist: Variables mutated inside steps are NOT preserved across replays — return values from steps instead
- Side effects outside steps that repeat on replay: Use
context.logger for logging (it is replay-aware and deduplicates automatically)
When implementing or modifying tests for durable functions, ALWAYS verify:
- All operations have descriptive names
- Tests get operations by NAME, never by index
- Replay behavior is tested with multiple invocations
- Use
LocalDurableTestRunner for local testing
MCP Server Configuration
Write access is enabled by default. The plugin ships with --allow-write in .mcp.json, so the MCP server can create projects, generate IaC, and deploy on behalf of the user.
Access to sensitive data (like Lambda and API Gateway logs) is not enabled by default. To grant it, add --allow-sensitive-data-access to .mcp.json.
Resources
1---2name: aws-lambda-durable-functions3description: Build resilient, long-running, multi-step applications with AWS Lambda durable functions with automatic state persistence, retry logic, and orchestration for long-running executions. Covers the critical replay model, step operations, wait/callback patterns, error handling with saga pattern, testing with LocalDurableTestRunner. Triggers on phrases like: lambda durable functions, workflow orchestration, state machines, retry/checkpoint patterns, long-running stateful Lambda functions, saga pattern, human-in-the-loop callbacks, and reliable serverless applications.4---5
6# AWS Lambda durable functions
7
8Build resilient multi-step applications and AI workflows that can execute for up to 1 year while maintaining reliable progress despite interruptions.
9
10## Onboarding
11
12### Step 1: Validate Prerequisites
13
14Before using AWS Lambda durable functions, verify:
15
161. **AWS CLI** is installed (2.33.22 or higher) and configured:
17
18 ```bash
19 aws --version
20 aws sts get-caller-identity
21 ```
22
232. **Runtime environment** is ready:
24 - For TypeScript/JavaScript: Node.js 22+ (`node --version`)
25 - For Python: Python 3.11+ (`python --version`. Note that currently only Lambda runtime environments 3.13+ come with the Durable Execution SDK pre-installed. 3.11 is the min supported Python version by the Durable SDK itself, however, you could use OCI to bring your own container image with your own Python runtime + Durable SDK.)
26
273. **Deployment capability** exists (one of):
28 - AWS SAM CLI (`sam --version`) 1.153.1 or higher
29 - AWS CDK (`cdk --version`) v2.237.1 or higher
30 - Direct Lambda deployment access
31
32### Step 2: Select language and IaC framework
33
34### Language Selection
35
36Default: TypeScript
37
38Override syntax:
39
40- "use Python" → Generate Python code
41- "use JavaScript" → Generate JavaScript code
42
43When not specified, ALWAYS use TypeScript
44
45### IaC framework selection
46
47Default: CDK
48
49Override syntax:
50
51- "use CloudFormation" → Generate YAML templates
52- "use SAM" → Generate YAML templates
53
54When not specified, ALWAYS use CDK
55
56### Error Scenarios
57
58#### Unsupported Language
59
60- List detected language
61- State: "Durable Execution SDK is not yet available for [framework]"
62- Suggest supported languages as alternatives
63
64#### Unsupported IaC Framework
65
66- List detected framework
67- State: "[framework] might not support Lambda durable functions yet"
68- Suggest supported frameworks as alternatives
69
70### Serverless MCP Server Unavailable
71
72- Inform user: "AWS Serverless MCP not responding"
73- Ask: "Proceed without MCP support?"
74- DO NOT continue without user confirmation
75
76### Step 3: Install SDK
77
78**For TypeScript/JavaScript:**
79
80```bash
81npm install @aws/durable-execution-sdk-js
82npm install --save-dev @aws/durable-execution-sdk-js-testing
83```
84
85**For Python:**
86
87```bash
88pip install aws-durable-execution-sdk-python
89pip install aws-durable-execution-sdk-python-testing
90```
91
92## When to Load Reference Files
93
94Load the appropriate reference file based on what the user is working on:
95
96- **Getting started**, **basic setup**, **example**, **ESLint**, or **Jest setup** -> see [getting-started.md](references/getting-started.md)
97- **Understanding replay model**, **determinism**, or **non-deterministic errors** -> see [replay-model-rules.md](references/replay-model-rules.md)
98- **Creating steps**, **atomic operations**, or **retry logic** -> see [step-operations.md](references/step-operations.md)
99- **Waiting**, **delays**, **callbacks**, **external systems**, or **polling** -> see [wait-operations.md](references/wait-operations.md)
100- **Parallel execution**, **map operations**, **batch processing**, or **concurrency** -> see [concurrent-operations.md](references/concurrent-operations.md)
101- **Error handling**, **retry strategies**, **saga pattern**, or **compensating transactions** -> see [error-handling.md](references/error-handling.md)
102- **Advanced error handling**, **timeout handling**, **circuit breakers**, or **conditional retries** -> see [advanced-error-handling.md](references/advanced-error-handling.md)
103- **Testing**, **local testing**, **cloud testing**, **test runner**, or **flaky tests** -> see [testing-patterns.md](references/testing-patterns.md)
104- **Deployment**, **CloudFormation**, **CDK**, **SAM**, **log groups**, **deploy**, or **infrastructure** -> see [deployment-iac.md](references/deployment-iac.md)
105- **Advanced patterns**, **GenAI agents**, **completion policies**, **step semantics**, or **custom serialization** -> see [advanced-patterns.md](references/advanced-patterns.md)
106- **troubleshooting**, **stuck execution**, **failed execution**, **debug execution ID**, or **execution history** -> see [troubleshooting-executions.md](references/troubleshooting-executions.md)
107
108## Quick Reference
109
110### Basic Handler Pattern
111
112**TypeScript:**
113
114```typescript
115import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
116
117export const handler = withDurableExecution(async (event, context: DurableContext) => {
118 const result = await context.step('process', async () => processData(event));
119 return result;
120});
121```
122
123**Python:**
124
125```python
126from aws_durable_execution_sdk_python import durable_execution, DurableContext
127
128@durable_execution
129def handler(event: dict, context: DurableContext) -> dict:
130 result = context.step(lambda _: process_data(event), name='process')
131 return result
132```
133
134### Critical Rules
135
1361. **All non-deterministic code MUST be in steps** (Date.now, Math.random, API calls)
1372. **Cannot nest durable operations** - use `runInChildContext` to group operations
1383. **Closure mutations are lost on replay** - return values from steps
1394. **Side effects outside steps repeat** - use `context.logger` (replay-aware)
140
141### Python API Differences
142
143The Python SDK differs from TypeScript in several key areas:
144
145- **Steps**: Use `@durable_step` decorator + `context.step(my_step(args))`, or inline `context.step(lambda _: ..., name='...')`. Prefer the decorator for automatic step naming.
146- **Wait**: `context.wait(duration=Duration.from_seconds(n), name='...')`
147- **Exceptions**: `ExecutionError` (permanent), `InvocationError` (transient), `CallbackError` (callback failures)
148- **Testing**: Use `DurableFunctionTestRunner` class directly - instantiate with handler, use context manager, call `run(input=...)`
149
150### Invocation Requirements
151
152Durable functions **require qualified ARNs** (version, alias, or `$LATEST`):
153
154```bash
155# Valid
156aws lambda invoke --function-name my-function:1 output.json
157aws lambda invoke --function-name my-function:prod output.json
158
159# Invalid - will fail
160aws lambda invoke --function-name my-function output.json
161```
162
163## IAM Permissions
164
165Your Lambda execution role MUST have the `AWSLambdaBasicDurableExecutionRolePolicy` managed policy attached. This includes:
166
167- `lambda:CheckpointDurableExecution` - Persist execution state
168- `lambda:GetDurableExecutionState` - Retrieve execution state
169- CloudWatch Logs permissions
170
171**Additional permissions needed for:**
172
173- **Durable invokes**: `lambda:InvokeFunction` on target function ARNs
174- **External callbacks**: Systems need `lambda:SendDurableExecutionCallbackSuccess` and `lambda:SendDurableExecutionCallbackFailure`
175
176## Validation Guidelines
177
178When writing or reviewing durable function code, ALWAYS check for these replay model violations:
179
1801. **Non-deterministic code outside steps**: `Date.now()`, `Math.random()`, UUID generation, API calls, database queries must all be inside steps
1812. **Nested durable operations in step functions**: Cannot call `context.step()`, `context.wait()`, or `context.invoke()` inside a step function — use `context.runInChildContext()` instead
1823. **Closure mutations that won't persist**: Variables mutated inside steps are NOT preserved across replays — return values from steps instead
1834. **Side effects outside steps that repeat on replay**: Use `context.logger` for logging (it is replay-aware and deduplicates automatically)
184
185When implementing or modifying tests for durable functions, ALWAYS verify:
186
1871. All operations have descriptive names
1882. Tests get operations by NAME, never by index
1893. Replay behavior is tested with multiple invocations
1904. Use `LocalDurableTestRunner` for local testing
191
192### MCP Server Configuration
193
194**Write access is enabled by default.** The plugin ships with `--allow-write` in `.mcp.json`, so the MCP server can create projects, generate IaC, and deploy on behalf of the user.
195
196Access to sensitive data (like Lambda and API Gateway logs) is **not** enabled by default. To grant it, add `--allow-sensitive-data-access` to `.mcp.json`.
197
198## Resources
199
200- [AWS Lambda durable functions Documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
201- [JavaScript SDK Repository](https://github.com/aws/aws-durable-execution-sdk-js)
202- [Python SDK Repository](https://github.com/aws/aws-durable-execution-sdk-python)
203- [IAM Policy Reference](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicDurableExecutionRolePolicy.html)