New pattern - lambda-managed-instances-bedrock-cdk#3076
Conversation
Deploy Lambda on EC2-backed Managed Instances with Bedrock (Claude) integration. Uses CapacityProvider L2 construct with ARM64 architecture, VPC with private subnets, and least-privilege IAM scoped to inference profile ARN. Differentiates from existing hello-world pattern by demonstrating a real-world Bedrock invocation use case on Managed Instances.
|
Hi @biswanathmukherjee 👋 Friendly nudge — this pattern is ready for review. Deployed and tested end-to-end on a live AWS account. Would appreciate a look when you have time. Thank you! |
|
Hi @biswanathmukherjee 👋 This shows Lambda Managed Instances (April 2026 GA) — a brand new compute mode where Lambda runs on customer-chosen EC2 instance types (Graviton). First real-world pattern beyond hello-world. Unique service integration. |
|
Hi @bfreiberg 👋 — friendly nudge on this pattern. It's been deployed and tested end-to-end on a live AWS account. Happy to address any feedback. Thank you! |
| actions: ["bedrock:InvokeModel"], | ||
| resources: [ | ||
| `arn:aws:bedrock:${this.region}:${this.account}:inference-profile/${modelId.valueAsString}`, | ||
| "arn:aws:bedrock:*::foundation-model/*", | ||
| ], | ||
| }) | ||
| ); | ||
|
|
There was a problem hiding this comment.
Bedrock IAM resource list is too broad. arn:aws:bedrock:*::foundation-model/* permits InvokeModel against every foundation model in every region.
For the default cross-region inference profile us.anthropic.claude-sonnet-4-20250514-v1:0, scope to the destination regions only.
There was a problem hiding this comment.
Good point -- scoped it down to the three US regions that the cross-region inference profile routes to (us-east-1, us-east-2, us-west-2) instead of the wildcard.
| capacityProvider.addFunction(fn); | ||
|
|
||
| new cdk.CfnOutput(this, "FunctionName", { value: fn.functionName }); | ||
| new cdk.CfnOutput(this, "FunctionArn", { value: fn.functionArn }); |
There was a problem hiding this comment.
The function will not become ACTIVE on the capacity provider until a version is published. Per https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances-getting-started.html step 5: "To run your function on Lambda Managed Instances, you must publish a version."
Without this, cdk deploy may succeed but aws lambda invoke could return the in-place $LATEST and will not execute on Managed Instances.
There was a problem hiding this comment.
You're right -- added fn.currentVersion + a prod alias. Without a published version the function stays on $LATEST and won't actually run on the capacity provider.
| }); | ||
|
|
||
| const capacityProvider = new lambda.CapacityProvider(this, "CapacityProvider", { | ||
| capacityProviderName: "bedrock-capacity-provider", |
There was a problem hiding this comment.
capacityProviderName: "bedrock-capacity-provider" is hardcoded. Capacity-provider names must be unique per account/region (validateCapacityProviderName in the CDK source). The same stack deployed twice in one account will fail. Drop the explicit name (CDK will generate one) or prefix with the stack name.
There was a problem hiding this comment.
Makes sense -- dropped the hardcoded name, letting CDK generate a unique one.
| const vpc = new ec2.Vpc(this, "ManagedInstancesVpc", { | ||
| maxAzs: 2, | ||
| natGateways: 1, | ||
| }); | ||
|
|
There was a problem hiding this comment.
The VPC creates a NAT gateway and Bedrock traffic egresses through it. Adding interface endpoints removes the NAT requirement and keeps Bedrock traffic on the AWS network.
If endpoints are intentionally omitted to keep the example minimal, please call out the NAT trade-off in the README.
There was a problem hiding this comment.
Keeping it minimal intentionally -- added a note in the README calling out the NAT trade-off and recommending a Bedrock VPC endpoint for production.
| const { BedrockRuntimeClient, InvokeModelCommand } = require("@aws-sdk/client-bedrock-runtime"); | ||
|
|
||
| const client = new BedrockRuntimeClient(); | ||
| const MODEL_ID = process.env.MODEL_ID; |
There was a problem hiding this comment.
If MODEL_ID is unset the handler would proceed with undefined and the SDK call would fail with an opaque ValidationException. Should fail fast at module load?
There was a problem hiding this comment.
Agreed -- added a throw at module load so it fails immediately with a clear message instead of a cryptic SDK error.
| exports.handler = async (event) => { | ||
| const prompt = event.prompt || "What are the benefits of Lambda Managed Instances?"; | ||
|
|
||
| const res = await client.send( |
There was a problem hiding this comment.
Missing exception handling in case of failed SDK calls
| ## Architecture | ||
|
|
||
| ``` | ||
| User → Lambda Function (on Managed Instances / EC2) | ||
| ├── VPC with private subnets | ||
| ├── CapacityProvider (ARM64) | ||
| └── Bedrock InvokeModel → Claude response | ||
| ``` |
There was a problem hiding this comment.
Folder structure is not architecture
There was a problem hiding this comment.
Fair -- replaced with a proper flow diagram showing Client → Lambda (Managed Instances) → Bedrock.
| ```bash | ||
| aws lambda invoke \ | ||
| --function-name managed-instances-bedrock-cdk \ | ||
| --payload '{"prompt":"Explain Lambda Managed Instances in 3 sentences"}' \ | ||
| --cli-binary-format raw-in-base64-out \ | ||
| output.json && cat output.json | python3 -m json.tool | ||
| ``` |
There was a problem hiding this comment.
If the stack publishes a version (recommended in another comment), this invoke should target the published version
There was a problem hiding this comment.
Updated the invoke command to target the prod alias with --qualifier prod.
- Narrowed foundation-model/* wildcard to specific us-east-1/us-east-2/ us-west-2 regions for the default Claude Sonnet inference profile - Added published version + alias (required for Managed Instances execution per docs step 5)
30b480a to
021c5ee
Compare
New Serverless Pattern: Lambda Managed Instances + Bedrock (CDK)
Description
Deploys a Lambda function on Managed Instances (EC2-backed compute) that invokes Amazon Bedrock (Claude) for text generation. Demonstrates a real-world Bedrock use case beyond the existing hello-world Managed Instances pattern.
Architecture
Key Features
nodejs24.xruntime, CloudWatch loggingBugs Found & Fixed During Deploy
memorySize >= 2048MB (not the default 128 MB)nodejs24.xruntime (notnodejs22.x)architecture: ARM_64must match CapacityProvider architectureDeployed & Tested ✅
Deployed to a live AWS account and tested end-to-end. Bedrock (Claude) returned a valid response via Lambda on Managed Instances.
Files
lib/lambda-managed-instances-bedrock-stack.ts— CDK stacksrc/index.js— Lambda handler (Bedrock invocation)example-pattern.json— Pattern metadataREADME.md— Full documentation with architecture, deploy, and test instructions