Skip to content

New serverless pattern - lambda-durable-bedrock-cdk#3053

Merged
julianwood merged 5 commits intoaws-samples:mainfrom
NithinChandranR-AWS:NithinChandranR-AWS-feature-lambda-durable-bedrock-cdk
May 5, 2026
Merged

New serverless pattern - lambda-durable-bedrock-cdk#3053
julianwood merged 5 commits intoaws-samples:mainfrom
NithinChandranR-AWS:NithinChandranR-AWS-feature-lambda-durable-bedrock-cdk

Conversation

@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor

@NithinChandranR-AWS NithinChandranR-AWS commented Apr 17, 2026

New Serverless Pattern: Lambda Durable Functions with Amazon Bedrock

Description

Deploys a Lambda durable function that orchestrates a multi-step AI content pipeline using Amazon Bedrock (Claude). Each step is automatically checkpointed — if the function is interrupted, it resumes from the last completed step without re-invoking Bedrock.

Architecture

Invoke → Lambda Durable Function → Bedrock (Claude)
Step 1: Generate Outline ✓ checkpoint
Wait: 5s (simulate review) ✓ checkpoint
Step 2: Expand Draft ✓ checkpoint
Step 3: Summarize ✓ checkpoint

Key Features

  • Uses @aws/durable-execution-sdk-js with automatic checkpointing
  • DurableExecution: { Enabled: true } via CfnFunction escape hatch
  • 3 Bedrock invocations + 1 wait operation, all checkpointed
  • Eliminates need for Step Functions in tightly-coupled AI workflows

Framework / Language

  • AWS CDK (TypeScript)
  • Lambda runtime: Node.js 20.x

Testing

  • Includes CLI invoke commands and durable execution status check
  • CDK synth verified (9 CloudFormation resources)

- Fix Bedrock model ID default (add -v1:0 suffix for inference profile)
- Fix DurableExecution → DurableConfig with ExecutionTimeout
- Override runtime to nodejs24.x (required for durable functions)
- Remove logRetention to avoid circular dependency with CfnVersion
- Use wildcard resource for durable execution IAM permissions

Tested: CDK synth verified, deployed to AWS account
fn.addToRolePolicy(
new iam.PolicyStatement({
actions: ["bedrock:InvokeModel"],
resources: ["*"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too permissive. Can you make it as restrictive as possible to support this use case? Please try out different variation and use what is feasible.

For example,

  new iam.PolicyStatement({
    actions: ["bedrock:InvokeModel"],
    resources: [
      `arn:aws:bedrock:${this.region}:${this.account}:inference-profile/${modelId.valueAsString}`,
      `arn:aws:bedrock:*::foundation-model/*`,
    ],
  })
);```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scoped it down to the specific inference profile ARN and foundation-model/*. The double colon (empty account) is needed because cross-region inference profiles resolve to foundation models in service-owned accounts. Fixed in 7a68a28.

"lambda:CheckpointDurableExecution",
"lambda:GetDurableExecutionState",
],
resources: ["*"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too permissive. Can you make it as restrictive as possible to support this use case? Please try out different variation and use what is feasible.

For example:

  new iam.PolicyStatement({
    actions: [
      "lambda:CheckpointDurableExecution",
      "lambda:GetDurableExecutionState",
    ],
    resources: [fn.functionArn, `${fn.functionArn}:*`],
  })
);```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced the inline policy with the AWSLambdaBasicDurableExecutionRolePolicy managed policy, which covers both lambda:CheckpointDurableExecution and lambda:GetDurableExecutionState. Fixed in 7a68a28.


// Durable execution permissions (wildcard to avoid circular dep)
fn.addToRolePolicy(
new iam.PolicyStatement({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding in-line policy to the the role, can you try with AWS Managed policy AWSLambdaBasicDurableExecutionRolePolicy.

Policy definition: https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicDurableExecutionRolePolicy.html

Example of how to use this policy: https://docs.aws.amazon.com/lambda/latest/dg/durable-getting-started-iac.html

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — switched to AWSLambdaBasicDurableExecutionRolePolicy managed policy via fn.role.addManagedPolicy(). This also covers CloudWatch Logs, complementing the default AWSLambdaBasicExecutionRole. Fixed in 7a68a28.

Comment thread lambda-durable-bedrock-cdk/README.md Outdated

## Testing

1. Invoke the durable function (use the published version from the output):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be specific that user needs to replace <FunctionName> with the value from deploy output.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated — testing instructions now explicitly say to replace and with the values from deploy output, with a concrete example. Fixed in 7a68a28.

Comment thread lambda-durable-bedrock-cdk/README.md Outdated
output.json
```

2. Since the function includes a wait, the initial invocation returns quickly. Check the durable execution status:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be specific that user needs to replace <FunctionName> with the value from deploy output.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same fix as above — both invoke and status-check commands now reference the deploy output values with examples. Fixed in 7a68a28.

@@ -0,0 +1,61 @@
{
"title": "Lambda Durable Functions with Amazon Bedrock",
"description": "Use AWS Lambda durable functions to orchestrate a multi-step AI content pipeline with Amazon Bedrock, featuring automatic checkpointing and failure recovery.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description needs to be 150 char or less.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed to 128 characters. Fixed in 7a68a28.

@@ -0,0 +1,61 @@
{
"title": "Lambda Durable Functions with Amazon Bedrock",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWS Lambda durable functions with Amazon Bedrock

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to match. Fixed in 7a68a28.

Comment thread lambda-durable-bedrock-cdk/README.md Outdated
@@ -0,0 +1,97 @@
# Lambda Durable Functions with Amazon Bedrock
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWS Lambda durable functions with Amazon Bedrock

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to match. Fixed in 7a68a28.

--cli-binary-format raw-in-base64-out \
output.json
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this:

aws lambda invoke \
  --function-name LambdaDurableBedrockStack-DurableBedrockFn3CE0D50D-FF9phCg6tiT9 \              
  --qualifier 1 \
  --payload '{"topic": "Serverless AI workflows with Lambda durable functions"}' \
  --cli-binary-format raw-in-base64-out \
  output.json

got this error:

aws: [ERROR]: An error occurred (ResourceNotFoundException) when calling the Invoke operation: Function not found: arn:aws:lambda:us-east-1:123456789012:function:LambdaDurableBedrockStack-DurableBedrockFn3CE0D50D-FF9phCg6tiT9:1

Additional error details:
Type: User

Then I tried this:

 aws lambda invoke \
  --function-name arn:aws:cloudformation:us-east-1:123456789012:stack/LambdaDurableBedrockStack/703aed20-3d3f-11f1-8f52-0affe2f2e12f \              
  --qualifier 1 \
  --payload '{"topic": "Serverless AI workflows with Lambda durable functions"}' \
  --cli-binary-format raw-in-base64-out \
  output.json

Got this error:

aws: [ERROR]: An error occurred (ValidationException) when calling the Invoke operation: 1 validation error detected: Value 'arn:aws:cloudformation:us-east-1:123456789012:stack/LambdaDurableBedrockStack/703aed20-3d3f-11f1-8f52-0affe2f2e12f' at 'functionName' failed to satisfy constraint: Member must satisfy regular expression pattern: (arn:(aws[a-zA-Z-]*)?:lambda:)?((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_\.]+)(:(\$LATEST(\.PUBLISHED)?|[a-zA-Z0-9-_]+))?
zsh: command not found: --qualifier

Please provide clearer instruction for testing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed -- the stack now publishes a Lambda version (CfnVersion) and exports FunctionVersion in outputs. README rewritten with explicit instructions to use FunctionName and FunctionVersion from cdk deploy output. Fixed in 7a68a28.

- Scope Bedrock InvokeModel to inference-profile and foundation-model
  ARNs instead of wildcard
- Replace inline durable execution policy with
  AWSLambdaBasicDurableExecutionRolePolicy managed policy
- Publish a Lambda version via CfnVersion for qualified invocation
- Add FunctionVersion output for testing instructions
- Fix README title, clarify testing with explicit placeholder replacement
- Trim example-pattern.json description to 128 chars
@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor Author

Hello Bishwajit,

Thank you for taking time and reviewing. Appreciate it.

I've updated each of the comments. Please help review this.

@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor Author

Hi @biswanathmukherjee — just a gentle follow-up. I've addressed all 9 review comments in commit 7a68a28:

  • Scoped Bedrock IAM to specific inference profile ARN + foundation-model/*
  • Replaced inline durable execution policy with AWSLambdaBasicDurableExecutionRolePolicy managed policy
  • Trimmed example-pattern.json description to 128 chars
  • Rewrote testing instructions with explicit output references and CfnVersion

Would you be able to take another look when you get a chance? Thank you!

NithinChandranR-AWS added a commit to NithinChandranR-AWS/serverless-patterns that referenced this pull request Apr 24, 2026
Replace inline durable execution policy (wildcard resources) with the
AWS managed policy for least-privilege IAM, matching the approach
recommended in PR aws-samples#3053 review feedback.
@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor Author

Hi @biswanathmukherjee — all 9 review comments have been addressed in commit 7a68a28 (scoped IAM, managed policy, clearer testing instructions, title/description fixes). Would appreciate a re-review when you have a moment. Thank you!

@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor Author

Hi @biswanathmukherjee 👋 Friendly follow-up — I addressed all 9 review comments in commit 7a68a28 (Apr 21). Would you be able to take another look when you get a chance? Happy to make any further changes. Thank you!

@NithinChandranR-AWS
Copy link
Copy Markdown
Contributor Author

Hi @biswanathmukherjee 👋 Gentle follow-up — all 9 review comments were addressed in commit 7a68a28 back on Apr 21. Would really appreciate a re-review when you get a chance. Happy to make any further changes needed. Thank you!

aws lambda list-durable-executions \
--function-name <FunctionName> \
--qualifier <Version>
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got the following error:

aws lambda list-durable-executions
--function-name arn:aws:lambda:us-east-1:123456789012:function:LambdaDurableBedrockStack-DurableBedrockFn3CE0D50D-FF9phCg6tiT9
--qualifier 1

aws: [ERROR]: An error occurred (ParamValidation): argument operation: Found invalid choice 'list-durable-executions'

Maybe you meant:

  • stop-durable-execution
  • get-durable-execution
  • get-durable-execution-state

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Fixed in 9fddf04 — the correct CLI command is list-durable-executions-by-function, not list-durable-executions. Thank you for testing this end-to-end!

@biswanathmukherjee
Copy link
Copy Markdown
Contributor

biswanathmukherjee commented May 5, 2026

@NithinChandranR-AWS Thanks for the fixes. However, one more error identified while testing now. Can you please fix that?

The AWS CLI command is 'list-durable-executions-by-function', not
'list-durable-executions'. Fixed per reviewer testing feedback.
@biswanathmukherjee
Copy link
Copy Markdown
Contributor

@NithinChandranR-AWS Thanks for your contribution. This pattern guardian approved. It will be reviewed by DA next.

@julianwood julianwood merged commit 943612c into aws-samples:main May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants