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