Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lambda-snapstart-bedrock-cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.js
!src/*.js
*.d.ts
node_modules
cdk.out
package-lock.json
3 changes: 3 additions & 0 deletions lambda-snapstart-bedrock-cdk/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.ts
!*.d.ts
cdk.out
87 changes: 87 additions & 0 deletions lambda-snapstart-bedrock-cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Lambda SnapStart with Amazon Bedrock

This pattern deploys a Python Lambda function with **SnapStart** enabled that invokes Amazon Bedrock (Claude Sonnet) for text generation, using AWS CDK.

Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/lambda-snapstart-bedrock-cdk

Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.

## Requirements

- [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
- [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) installed
- [Node.js](https://nodejs.org/) 18.x or later
- [Amazon Bedrock model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) enabled for Anthropic Claude Sonnet in your AWS account

## How it works

Lambda SnapStart reduces cold start latency by up to 10x by pre-initializing the execution environment and caching a snapshot of the initialized state. When a new execution environment is needed, Lambda restores from the cached snapshot instead of running full initialization.

**Key points:**
- SnapStart is enabled via `snapStart: lambda.SnapStartConf.ON_PUBLISHED_VERSIONS` in CDK
- SnapStart only applies to **published versions**, not `$LATEST` — the pattern creates a version and alias automatically
- Supported runtimes: Java 11/17/21, Python 3.12/3.13, .NET 8
- The Bedrock client is initialized at module level (outside the handler) so it gets captured in the SnapStart snapshot

```
┌──────────────────────┐ ┌──────────────────────┐
│ │ │ │
│ Lambda (SnapStart) │────────▶│ Amazon Bedrock │
│ Python 3.13 │ │ Claude Sonnet │
│ │◀────────│ │
└──────────────────────┘ └──────────────────────┘
```

## Deployment

1. Install dependencies:
```bash
cd lambda-snapstart-bedrock-cdk
npm install
```

2. Deploy the stack:
```bash
cdk deploy
```

## Testing

Invoke the function via the **alias** (SnapStart only applies to published versions):

```bash
aws lambda invoke \
--function-name snapstart-bedrock-cdk:live \
--payload '{"prompt": "Explain Lambda SnapStart in one paragraph"}' \
--cli-binary-format raw-in-base64-out \
output.json

cat output.json | python3 -m json.tool
```

To compare cold start times, invoke `$LATEST` (no SnapStart) vs the alias (with SnapStart):

```bash
# Without SnapStart ($LATEST)
aws lambda invoke --function-name snapstart-bedrock-cdk \
--payload '{"prompt": "Hello"}' --cli-binary-format raw-in-base64-out /dev/null

# With SnapStart (alias)
aws lambda invoke --function-name snapstart-bedrock-cdk:live \
--payload '{"prompt": "Hello"}' --cli-binary-format raw-in-base64-out /dev/null
```

Check the `Init Duration` in CloudWatch Logs — SnapStart-optimized invocations show `Restore Duration` instead, which is significantly lower.

## Cleanup

```bash
cdk destroy
```

---

Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: MIT-0
7 changes: 7 additions & 0 deletions lambda-snapstart-bedrock-cdk/bin/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { LambdaSnapstartBedrockStack } from "../lib/lambda-snapstart-bedrock-stack";

const app = new cdk.App();
new LambdaSnapstartBedrockStack(app, "LambdaSnapstartBedrockStack");
7 changes: 7 additions & 0 deletions lambda-snapstart-bedrock-cdk/cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"acknowledged-issue-numbers": [
33623,
34635,
34892
]
}
3 changes: 3 additions & 0 deletions lambda-snapstart-bedrock-cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "npx ts-node bin/app.ts"
}
52 changes: 52 additions & 0 deletions lambda-snapstart-bedrock-cdk/example-pattern.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"title": "Lambda SnapStart with Amazon Bedrock",
"description": "Invoke Amazon Bedrock from a Lambda function with SnapStart enabled for dramatically reduced cold start latency, deployed with AWS CDK.",
"language": "Python",
"level": "200",
"framework": "CDK",
"introBox": {
"headline": "How it works",
"text": [
"This pattern deploys a Python Lambda function with SnapStart enabled that invokes Amazon Bedrock (Claude Sonnet) for text generation.",
"Lambda SnapStart reduces cold start latency by up to 10x by pre-initializing the execution environment and caching a snapshot of the initialized state.",
"When a new execution environment is needed, Lambda restores from the cached snapshot instead of running full initialization, providing near-instant cold starts.",
"A published version and alias are created to activate SnapStart optimization — SnapStart only applies to published versions, not $LATEST."
]
},
"gitHub": {
"template": {
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-snapstart-bedrock-cdk",
"templateURL": "serverless-patterns/lambda-snapstart-bedrock-cdk",
"projectFolder": "lambda-snapstart-bedrock-cdk",
"templateFile": "lib/lambda-snapstart-bedrock-stack.ts"
}
},
"resources": {
"bullets": [
{ "text": "Lambda SnapStart documentation", "link": "https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html" },
{ "text": "Lambda SnapStart for Python and .NET", "link": "https://aws.amazon.com/blogs/aws/reduce-cold-starts-for-your-lambda-functions-with-snapstart-for-python-and-net/" },
{ "text": "Amazon Bedrock documentation", "link": "https://docs.aws.amazon.com/bedrock/latest/userguide/" }
]
},
"deploy": {
"text": ["cdk deploy"]
},
"testing": {
"text": ["See the README for testing instructions."]
},
"cleanup": {
"text": ["cdk destroy"]
},
"authors": [
{
"name": "Nithin Chandran R",
"bio": "Technical Account Manager at AWS",
"linkedin": "nithin-chandran-r"
}
],
"patternArch": {
"icon1": { "x": 20, "y": 50, "service": "lambda", "label": "Lambda (SnapStart)" },
"icon2": { "x": 80, "y": 50, "service": "bedrock", "label": "Amazon Bedrock" },
"line1": { "from": "icon1", "to": "icon2" }
}
}
63 changes: 63 additions & 0 deletions lambda-snapstart-bedrock-cdk/lib/lambda-snapstart-bedrock-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as iam from "aws-cdk-lib/aws-iam";
import * as logs from "aws-cdk-lib/aws-logs";
import { Construct } from "constructs";

export class LambdaSnapstartBedrockStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const modelId = new cdk.CfnParameter(this, "BedrockModelId", {
type: "String",
default: "us.anthropic.claude-sonnet-4-20250514-v1:0",
description: "Bedrock inference profile model ID",
});

const functionName = "snapstart-bedrock-cdk";

const logGroup = new logs.LogGroup(this, "LogGroup", {
logGroupName: `/aws/lambda/${functionName}`,
retention: logs.RetentionDays.TWO_WEEKS,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});

const fn = new lambda.Function(this, "BedrockFn", {
runtime: lambda.Runtime.PYTHON_3_13,
handler: "index.handler",
code: lambda.Code.fromAsset("src"),
timeout: cdk.Duration.seconds(30),
memorySize: 512,
functionName,
description: "Bedrock invocation with SnapStart for reduced cold starts",
loggingFormat: lambda.LoggingFormat.JSON,
logGroup,
snapStart: lambda.SnapStartConf.ON_PUBLISHED_VERSIONS,
environment: { MODEL_ID: modelId.valueAsString },
});

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

// Publish a version to activate SnapStart
const version = fn.currentVersion;

// Alias pointing to the SnapStart-optimized version
const alias = new lambda.Alias(this, "LiveAlias", {
aliasName: "live",
version,
});

new cdk.CfnOutput(this, "FunctionName", { value: fn.functionName });
new cdk.CfnOutput(this, "FunctionArn", { value: fn.functionArn });
new cdk.CfnOutput(this, "AliasArn", { value: alias.functionArn });
new cdk.CfnOutput(this, "LogGroupName", { value: logGroup.logGroupName });
}
}
15 changes: 15 additions & 0 deletions lambda-snapstart-bedrock-cdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "lambda-snapstart-bedrock-cdk",
"version": "1.0.0",
"bin": { "app": "bin/app.ts" },
"scripts": { "build": "tsc", "cdk": "cdk" },
"dependencies": {
"aws-cdk-lib": "2.236.0",
"constructs": "10.4.2"
},
"devDependencies": {
"@types/node": "^22.0.0",
"ts-node": "^10.9.0",
"typescript": "~5.7.0"
}
}
33 changes: 33 additions & 0 deletions lambda-snapstart-bedrock-cdk/src/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import json
import os
import boto3

bedrock = boto3.client("bedrock-runtime")
MODEL_ID = os.environ["MODEL_ID"]


def handler(event, context):
prompt = event.get("prompt", "What are the benefits of Lambda SnapStart?")

response = bedrock.invoke_model(
modelId=MODEL_ID,
contentType="application/json",
accept="application/json",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"messages": [{"role": "user", "content": prompt}],
}),
)

body = json.loads(response["body"].read())

return {
"statusCode": 200,
"body": json.dumps({
"prompt": prompt,
"response": body["content"][0]["text"],
"model": MODEL_ID,
"usage": body["usage"],
}),
}
22 changes: 22 additions & 0 deletions lambda-snapstart-bedrock-cdk/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["es2020"],
"declaration": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": false,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"strictPropertyInitialization": false
},
"exclude": ["cdk.out"]
}