Skip to content

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

Open
NithinChandranR-AWS wants to merge 3 commits intoaws-samples:mainfrom
NithinChandranR-AWS:NithinChandranR-AWS-feature-lambda-durable-bedrock-cdk
Open

New serverless pattern - lambda-durable-bedrock-cdk#3053
NithinChandranR-AWS wants to merge 3 commits intoaws-samples:mainfrom
NithinChandranR-AWS:NithinChandranR-AWS-feature-lambda-durable-bedrock-cdk

Conversation

@NithinChandranR-AWS
Copy link
Copy Markdown

@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
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
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
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
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
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
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
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
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
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
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
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants