From 012511f5a3c1b8b0a302720cce3cd4723f232398 Mon Sep 17 00:00:00 2001 From: Nithin Chandran Rajashankar Date: Sun, 3 May 2026 11:10:51 +0000 Subject: [PATCH 1/2] feat(aurora-serverless-v2-lambda-bedrock-cdk): Add Aurora Serverless v2 RAG with Bedrock Deploy Aurora Serverless v2 PostgreSQL (platform version 4, 30% perf boost) with Lambda functions that query stored knowledge via Data API and use Amazon Bedrock for AI-powered answers. Scales to zero. --- .../README.md | 81 +++++++++++++++++ .../bin/app.ts | 16 ++++ .../cdk.context.json | 60 +++++++++++++ .../cdk.json | 3 + .../example-pattern.json | 50 +++++++++++ ...rora-serverless-v2-lambda-bedrock-stack.ts | 90 +++++++++++++++++++ .../package.json | 15 ++++ .../src/query-fn/index.py | 53 +++++++++++ .../src/setup/index.py | 53 +++++++++++ .../tsconfig.json | 20 +++++ 10 files changed, 441 insertions(+) create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/README.md create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/bin/app.ts create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/cdk.json create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/package.json create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/src/query-fn/index.py create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/src/setup/index.py create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/tsconfig.json diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/README.md b/aurora-serverless-v2-lambda-bedrock-cdk/README.md new file mode 100644 index 0000000000..5a373400a6 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/README.md @@ -0,0 +1,81 @@ +# Aurora Serverless v2 with Lambda and Amazon Bedrock + +This pattern deploys an Aurora Serverless v2 PostgreSQL cluster (platform version 4) with Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers. Aurora Serverless v2 scales to zero when idle, making it cost-effective for agentic AI workloads. + +Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/aurora-serverless-v2-lambda-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 +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [Node and NPM](https://nodejs.org/en/download/) installed +* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) installed +* [Amazon Bedrock model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) enabled for Anthropic Claude Sonnet in your target region + +## How it works + +![Architecture](architecture.png) + +1. A setup Lambda creates the `knowledge` table in Aurora PostgreSQL and seeds it with sample data. +2. A query Lambda receives a question, searches Aurora for relevant context using SQL, and sends the context + question to Amazon Bedrock. +3. Bedrock (Claude Sonnet) generates an answer grounded in the database context. +4. Aurora Serverless v2 (platform version 4) automatically scales capacity based on demand and scales to zero when idle. + +## Deployment + +1. Clone the repository and navigate to the pattern directory: + ```bash + git clone https://github.com/aws-samples/serverless-patterns + cd serverless-patterns/aurora-serverless-v2-lambda-bedrock-cdk + ``` + +2. Install dependencies: + ```bash + npm install + ``` + +3. Deploy the stack: + ```bash + cdk deploy + ``` + +4. Seed the database: + ```bash + aws lambda invoke \ + --function-name $(aws cloudformation describe-stacks \ + --stack-name AuroraServerlessV2LambdaBedrockStack \ + --query 'Stacks[0].Outputs[?OutputKey==`SetupFunctionName`].OutputValue' \ + --output text) \ + --payload '{}' setup-output.json + ``` + +## Testing + +Query the knowledge base: + +```bash +aws lambda invoke \ + --function-name $(aws cloudformation describe-stacks \ + --stack-name AuroraServerlessV2LambdaBedrockStack \ + --query 'Stacks[0].Outputs[?OutputKey==`QueryFunctionName`].OutputValue' \ + --output text) \ + --cli-binary-format raw-in-base64-out \ + --payload '{"question": "What is Aurora Serverless v2?"}' \ + output.json + +cat output.json | python3 -m json.tool +``` + +## Cleanup + +```bash +cdk destroy +``` + +---- +Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/bin/app.ts b/aurora-serverless-v2-lambda-bedrock-cdk/bin/app.ts new file mode 100644 index 0000000000..555497d004 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/bin/app.ts @@ -0,0 +1,16 @@ +#!/usr/bin/env node +import "source-map-support/register"; +import * as cdk from "aws-cdk-lib"; +import { AuroraServerlessV2LambdaBedrockStack } from "../lib/aurora-serverless-v2-lambda-bedrock-stack"; + +const app = new cdk.App(); +new AuroraServerlessV2LambdaBedrockStack( + app, + "AuroraServerlessV2LambdaBedrockStack", + { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, + } +); diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json b/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json new file mode 100644 index 0000000000..1a91c74383 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json @@ -0,0 +1,60 @@ +{ + "availability-zones:account=742460038667:region=us-east-1": [ + "us-east-1a", + "us-east-1b", + "us-east-1c", + "us-east-1d", + "us-east-1e", + "us-east-1f" + ], + "vpc-provider:account=742460038667:filter.isDefault=true:region=us-east-1:returnAsymmetricSubnets=true": { + "vpcId": "vpc-0d2ccb9ba9da8174c", + "vpcCidrBlock": "172.31.0.0/16", + "ownerAccountId": "742460038667", + "availabilityZones": [], + "subnetGroups": [ + { + "name": "Public", + "type": "Public", + "subnets": [ + { + "subnetId": "subnet-09f81666a668b49d7", + "cidr": "172.31.16.0/20", + "availabilityZone": "us-east-1a", + "routeTableId": "rtb-0d6e0c8254189f150" + }, + { + "subnetId": "subnet-01e469e26a62f79cc", + "cidr": "172.31.32.0/20", + "availabilityZone": "us-east-1b", + "routeTableId": "rtb-0d6e0c8254189f150" + }, + { + "subnetId": "subnet-0edf680549fc43b35", + "cidr": "172.31.0.0/20", + "availabilityZone": "us-east-1c", + "routeTableId": "rtb-0d6e0c8254189f150" + }, + { + "subnetId": "subnet-0a4b73e1b77dfe7e3", + "cidr": "172.31.80.0/20", + "availabilityZone": "us-east-1d", + "routeTableId": "rtb-0d6e0c8254189f150" + }, + { + "subnetId": "subnet-007839dd58f1d60a0", + "cidr": "172.31.48.0/20", + "availabilityZone": "us-east-1e", + "routeTableId": "rtb-0d6e0c8254189f150" + }, + { + "subnetId": "subnet-03604e5a5796bce0a", + "cidr": "172.31.64.0/20", + "availabilityZone": "us-east-1f", + "routeTableId": "rtb-0d6e0c8254189f150" + } + ] + } + ] + } +} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/cdk.json b/aurora-serverless-v2-lambda-bedrock-cdk/cdk.json new file mode 100644 index 0000000000..a6700a2ff4 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/cdk.json @@ -0,0 +1,3 @@ +{ + "app": "npx ts-node --prefer-ts-exts bin/app.ts" +} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json b/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json new file mode 100644 index 0000000000..4454c57d17 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json @@ -0,0 +1,50 @@ +{ + "title": "Aurora Serverless v2 with Lambda and Amazon Bedrock", + "description": "Deploy an Aurora Serverless v2 PostgreSQL database that scales to zero, with Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers.", + "language": "Python", + "level": "300", + "framework": "AWS CDK", + "services": { + "from": "auroraserverlessv2", + "to": "bedrock" + }, + "introBox": { + "headline": "How it works", + "text": [ + "This pattern deploys an Aurora Serverless v2 PostgreSQL cluster (platform version 4 with up to 30% better performance) that scales to zero when idle. A setup Lambda seeds a knowledge table, and a query Lambda retrieves relevant context from Aurora and sends it to Amazon Bedrock for AI-powered answers.", + "Aurora Serverless v2 is ideal for agentic AI workloads with burst patterns and long idle windows. The enhanced scaling algorithm in platform version 4 efficiently handles workloads where multiple tasks compete for resources." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/aurora-serverless-v2-lambda-bedrock-cdk", + "templateURL": "serverless-patterns/aurora-serverless-v2-lambda-bedrock-cdk", + "projectFolder": "aurora-serverless-v2-lambda-bedrock-cdk", + "templateFile": "lib/aurora-serverless-v2-lambda-bedrock-stack.ts" + } + }, + "resources": { + "bullets": [ + { "text": "Aurora Serverless v2 platform version 4", "link": "https://aws.amazon.com/about-aws/whats-new/2026/04/aurora-serverless-smarter-scaling/" }, + { "text": "Amazon Aurora Serverless", "link": "https://aws.amazon.com/rds/aurora/serverless/" }, + { "text": "Amazon Bedrock", "link": "https://aws.amazon.com/bedrock/" } + ] + }, + "deploy": { + "text": ["cdk deploy"], + "file": "lib/aurora-serverless-v2-lambda-bedrock-stack.ts" + }, + "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" + } + ] +} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts b/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts new file mode 100644 index 0000000000..3d502e9482 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts @@ -0,0 +1,90 @@ +import * as cdk from "aws-cdk-lib"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as lambda from "aws-cdk-lib/aws-lambda"; +import * as rds from "aws-cdk-lib/aws-rds"; +import { Construct } from "constructs"; + +export class AuroraServerlessV2LambdaBedrockStack extends cdk.Stack { + constructor(scope: Construct, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + // Use default VPC + const vpc = ec2.Vpc.fromLookup(this, "DefaultVpc", { isDefault: true }); + + // Aurora Serverless v2 cluster (PostgreSQL, scales to zero) + const cluster = new rds.DatabaseCluster(this, "AuroraCluster", { + engine: rds.DatabaseClusterEngine.auroraPostgres({ + version: rds.AuroraPostgresEngineVersion.VER_16_4, + }), + serverlessV2MinCapacity: 0, + serverlessV2MaxCapacity: 4, + writer: rds.ClusterInstance.serverlessV2("writer"), + vpc, + vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + defaultDatabaseName: "appdb", + enableDataApi: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + + // Data API policy for Lambdas + const dataApiPolicy = new iam.PolicyStatement({ + actions: [ + "rds-data:ExecuteStatement", + "rds-data:BatchExecuteStatement", + ], + resources: [cluster.clusterArn], + }); + + const envVars = { + CLUSTER_ARN: cluster.clusterArn, + SECRET_ARN: cluster.secret!.secretArn, + DB_NAME: "appdb", + }; + + // Setup Lambda — initializes the knowledge table + const setupFn = new lambda.Function(this, "SetupFn", { + runtime: lambda.Runtime.PYTHON_3_12, + handler: "index.handler", + code: lambda.Code.fromAsset("src/setup"), + timeout: cdk.Duration.seconds(60), + memorySize: 256, + environment: envVars, + description: "Seeds Aurora knowledge table via Data API", + }); + cluster.secret!.grantRead(setupFn); + setupFn.addToRolePolicy(dataApiPolicy); + + // Query Lambda — queries Aurora, sends context to Bedrock + const queryFn = new lambda.Function(this, "QueryFn", { + runtime: lambda.Runtime.PYTHON_3_12, + handler: "index.handler", + code: lambda.Code.fromAsset("src/query-fn"), + timeout: cdk.Duration.minutes(2), + memorySize: 512, + environment: { + ...envVars, + MODEL_ID: "us.anthropic.claude-sonnet-4-20250514-v1:0", + }, + description: "Queries Aurora knowledge base and sends to Bedrock", + }); + cluster.secret!.grantRead(queryFn); + queryFn.addToRolePolicy(dataApiPolicy); + queryFn.addToRolePolicy( + new iam.PolicyStatement({ + actions: ["bedrock:InvokeModel"], + resources: ["*"], + }) + ); + + new cdk.CfnOutput(this, "SetupFunctionName", { + value: setupFn.functionName, + }); + new cdk.CfnOutput(this, "QueryFunctionName", { + value: queryFn.functionName, + }); + new cdk.CfnOutput(this, "ClusterEndpoint", { + value: cluster.clusterEndpoint.hostname, + }); + } +} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/package.json b/aurora-serverless-v2-lambda-bedrock-cdk/package.json new file mode 100644 index 0000000000..64e4f0c257 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/package.json @@ -0,0 +1,15 @@ +{ + "name": "aurora-serverless-v2-lambda-bedrock-cdk", + "version": "1.0.0", + "bin": { "app": "bin/app.ts" }, + "scripts": { "build": "tsc", "cdk": "cdk" }, + "dependencies": { + "aws-cdk-lib": "^2.180.0", + "constructs": "^10.4.2" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "ts-node": "^10.9.0", + "typescript": "~5.7.0" + } +} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/src/query-fn/index.py b/aurora-serverless-v2-lambda-bedrock-cdk/src/query-fn/index.py new file mode 100644 index 0000000000..ed781cf357 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/src/query-fn/index.py @@ -0,0 +1,53 @@ +"""Query handler — searches Aurora via Data API, sends context to Bedrock for answer.""" + +import json +import os +import boto3 + +rds_data = boto3.client("rds-data") +bedrock = boto3.client("bedrock-runtime") + +CLUSTER_ARN = os.environ["CLUSTER_ARN"] +SECRET_ARN = os.environ["SECRET_ARN"] +DB_NAME = os.environ["DB_NAME"] + + +def handler(event, _context): + question = event.get("question", "What is Aurora Serverless v2?") + stop_words = {"what", "is", "the", "a", "an", "how", "does", "do", "can", "tell", "me", "about"} + keywords = [w for w in question.split() if w.lower().strip("?.,!") not in stop_words] + search_term = keywords[0] if keywords else "Aurora" + + # Query Aurora for relevant knowledge via Data API + result = rds_data.execute_statement( + resourceArn=CLUSTER_ARN, + secretArn=SECRET_ARN, + database=DB_NAME, + sql="SELECT topic, content FROM knowledge WHERE content ILIKE :term OR topic ILIKE :term LIMIT 3", + parameters=[{"name": "term", "value": {"stringValue": f"%{search_term}%"}}], + ) + + rows = result.get("records", []) + context = "\n".join( + f"[{r[0]['stringValue']}]: {r[1]['stringValue']}" for r in rows + ) if rows else "No context found." + + # Send context + question to Bedrock + response = bedrock.invoke_model( + modelId=os.environ["MODEL_ID"], + contentType="application/json", + accept="application/json", + body=json.dumps({ + "anthropic_version": "bedrock-2023-05-31", + "max_tokens": 512, + "messages": [ + { + "role": "user", + "content": f"Context from database:\n{context}\n\nQuestion: {question}\n\nAnswer based on the context above.", + } + ], + }), + ) + answer = json.loads(response["body"].read())["content"][0]["text"] + + return {"statusCode": 200, "body": json.dumps({"question": question, "answer": answer, "sources": len(rows)})} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/src/setup/index.py b/aurora-serverless-v2-lambda-bedrock-cdk/src/setup/index.py new file mode 100644 index 0000000000..ec6aac6c85 --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/src/setup/index.py @@ -0,0 +1,53 @@ +"""Setup handler — creates the knowledge table and seeds sample data via RDS Data API.""" + +import json +import os +import boto3 + +rds_data = boto3.client("rds-data") + +CLUSTER_ARN = os.environ["CLUSTER_ARN"] +SECRET_ARN = os.environ["SECRET_ARN"] +DB_NAME = os.environ["DB_NAME"] + + +def execute(sql, params=None): + kwargs = { + "resourceArn": CLUSTER_ARN, + "secretArn": SECRET_ARN, + "database": DB_NAME, + "sql": sql, + } + if params: + kwargs["parameters"] = params + return rds_data.execute_statement(**kwargs) + + +def handler(event, _context): + execute(""" + CREATE TABLE IF NOT EXISTS knowledge ( + id SERIAL PRIMARY KEY, + topic TEXT NOT NULL, + content TEXT NOT NULL + ) + """) + + result = execute("SELECT count(*) FROM knowledge") + count = result["records"][0][0]["longValue"] + + if count == 0: + rows = [ + ("Aurora Serverless v2", "Aurora Serverless v2 platform version 4 delivers up to 30% better performance with enhanced scaling. It scales to zero when idle and is ideal for agentic AI workloads with burst patterns."), + ("Lambda", "AWS Lambda supports up to 10 GB memory, 15-minute timeout, and features like durable functions, SnapStart, managed instances, and S3 Files mounting."), + ("Bedrock", "Amazon Bedrock provides access to foundation models from Anthropic, Meta, Amazon, and OpenAI through a unified API with built-in security and governance."), + ] + for topic, content in rows: + execute( + "INSERT INTO knowledge (topic, content) VALUES (:topic, :content)", + [ + {"name": "topic", "value": {"stringValue": topic}}, + {"name": "content", "value": {"stringValue": content}}, + ], + ) + + return {"statusCode": 200, "body": f"Setup complete. Rows: {count + len(rows) if count == 0 else count}"} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/tsconfig.json b/aurora-serverless-v2-lambda-bedrock-cdk/tsconfig.json new file mode 100644 index 0000000000..9b34373a0d --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["es2020"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "outDir": "build", + "rootDir": ".", + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "esModuleInterop": true + }, + "exclude": ["node_modules", "build"] +} From 366979cd3a92d91191cdba14a95d5459b1de4a33 Mon Sep 17 00:00:00 2001 From: Nithin Chandran Rajashankar Date: Sun, 14 Jun 2026 17:27:47 +0000 Subject: [PATCH 2/2] fix: address marcojahn review comments on PR #3094 - Move Aurora cluster to private/isolated subnets (not public) - Scope bedrock:InvokeModel to specific model ARN - Add storageEncrypted: true to cluster - Delete cdk.context.json with real account ID, add to .gitignore - Replace broken architecture.png reference with text description - Add full service name prefixes (Amazon Aurora, AWS Lambda, Amazon Bedrock) - Fix service names in example-pattern.json --- .../.gitignore | 3 + .../README.md | 10 ++-- .../cdk.context.json | 60 ------------------- .../example-pattern.json | 8 +-- ...rora-serverless-v2-lambda-bedrock-stack.ts | 17 ++++-- 5 files changed, 26 insertions(+), 72 deletions(-) create mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/.gitignore delete mode 100644 aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/.gitignore b/aurora-serverless-v2-lambda-bedrock-cdk/.gitignore new file mode 100644 index 0000000000..9188c95d5d --- /dev/null +++ b/aurora-serverless-v2-lambda-bedrock-cdk/.gitignore @@ -0,0 +1,3 @@ +node_modules +cdk.out +cdk.context.json diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/README.md b/aurora-serverless-v2-lambda-bedrock-cdk/README.md index 5a373400a6..7d7b90ff3c 100644 --- a/aurora-serverless-v2-lambda-bedrock-cdk/README.md +++ b/aurora-serverless-v2-lambda-bedrock-cdk/README.md @@ -1,6 +1,6 @@ -# Aurora Serverless v2 with Lambda and Amazon Bedrock +# Amazon Aurora Serverless v2 with AWS Lambda and Amazon Bedrock -This pattern deploys an Aurora Serverless v2 PostgreSQL cluster (platform version 4) with Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers. Aurora Serverless v2 scales to zero when idle, making it cost-effective for agentic AI workloads. +This pattern deploys an Amazon Aurora Serverless v2 PostgreSQL cluster (platform version 4) with AWS Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers. Amazon Aurora Serverless v2 scales to zero when idle, making it cost-effective for agentic AI workloads. Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/aurora-serverless-v2-lambda-bedrock-cdk @@ -15,9 +15,11 @@ Important: this application uses various AWS services and there are costs associ * [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) installed * [Amazon Bedrock model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) enabled for Anthropic Claude Sonnet in your target region -## How it works +## Architecture + +The pattern creates a VPC with isolated subnets, an Amazon Aurora Serverless v2 PostgreSQL cluster (with encryption at rest), and two AWS Lambda functions. The setup function seeds data via the RDS Data API. The query function retrieves context from Aurora and passes it to Amazon Bedrock for AI-powered answers. -![Architecture](architecture.png) +## How it works 1. A setup Lambda creates the `knowledge` table in Aurora PostgreSQL and seeds it with sample data. 2. A query Lambda receives a question, searches Aurora for relevant context using SQL, and sends the context + question to Amazon Bedrock. diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json b/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json deleted file mode 100644 index 1a91c74383..0000000000 --- a/aurora-serverless-v2-lambda-bedrock-cdk/cdk.context.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "availability-zones:account=742460038667:region=us-east-1": [ - "us-east-1a", - "us-east-1b", - "us-east-1c", - "us-east-1d", - "us-east-1e", - "us-east-1f" - ], - "vpc-provider:account=742460038667:filter.isDefault=true:region=us-east-1:returnAsymmetricSubnets=true": { - "vpcId": "vpc-0d2ccb9ba9da8174c", - "vpcCidrBlock": "172.31.0.0/16", - "ownerAccountId": "742460038667", - "availabilityZones": [], - "subnetGroups": [ - { - "name": "Public", - "type": "Public", - "subnets": [ - { - "subnetId": "subnet-09f81666a668b49d7", - "cidr": "172.31.16.0/20", - "availabilityZone": "us-east-1a", - "routeTableId": "rtb-0d6e0c8254189f150" - }, - { - "subnetId": "subnet-01e469e26a62f79cc", - "cidr": "172.31.32.0/20", - "availabilityZone": "us-east-1b", - "routeTableId": "rtb-0d6e0c8254189f150" - }, - { - "subnetId": "subnet-0edf680549fc43b35", - "cidr": "172.31.0.0/20", - "availabilityZone": "us-east-1c", - "routeTableId": "rtb-0d6e0c8254189f150" - }, - { - "subnetId": "subnet-0a4b73e1b77dfe7e3", - "cidr": "172.31.80.0/20", - "availabilityZone": "us-east-1d", - "routeTableId": "rtb-0d6e0c8254189f150" - }, - { - "subnetId": "subnet-007839dd58f1d60a0", - "cidr": "172.31.48.0/20", - "availabilityZone": "us-east-1e", - "routeTableId": "rtb-0d6e0c8254189f150" - }, - { - "subnetId": "subnet-03604e5a5796bce0a", - "cidr": "172.31.64.0/20", - "availabilityZone": "us-east-1f", - "routeTableId": "rtb-0d6e0c8254189f150" - } - ] - } - ] - } -} diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json b/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json index 4454c57d17..279e85201b 100644 --- a/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json +++ b/aurora-serverless-v2-lambda-bedrock-cdk/example-pattern.json @@ -1,6 +1,6 @@ { - "title": "Aurora Serverless v2 with Lambda and Amazon Bedrock", - "description": "Deploy an Aurora Serverless v2 PostgreSQL database that scales to zero, with Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers.", + "title": "Amazon Aurora Serverless v2 with AWS Lambda and Amazon Bedrock", + "description": "Deploy an Amazon Aurora Serverless v2 PostgreSQL database that scales to zero, with AWS Lambda functions that query stored knowledge and use Amazon Bedrock for AI-powered answers.", "language": "Python", "level": "300", "framework": "AWS CDK", @@ -11,8 +11,8 @@ "introBox": { "headline": "How it works", "text": [ - "This pattern deploys an Aurora Serverless v2 PostgreSQL cluster (platform version 4 with up to 30% better performance) that scales to zero when idle. A setup Lambda seeds a knowledge table, and a query Lambda retrieves relevant context from Aurora and sends it to Amazon Bedrock for AI-powered answers.", - "Aurora Serverless v2 is ideal for agentic AI workloads with burst patterns and long idle windows. The enhanced scaling algorithm in platform version 4 efficiently handles workloads where multiple tasks compete for resources." + "This pattern deploys an Amazon Aurora Serverless v2 PostgreSQL cluster (platform version 4 with up to 30% better performance) that scales to zero when idle. A setup AWS Lambda seeds a knowledge table, and a query AWS Lambda retrieves relevant context from Aurora and sends it to Amazon Bedrock for AI-powered answers.", + "Amazon Aurora Serverless v2 is ideal for agentic AI workloads with burst patterns and long idle windows. The enhanced scaling algorithm in platform version 4 efficiently handles workloads where multiple tasks compete for resources." ] }, "gitHub": { diff --git a/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts b/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts index 3d502e9482..6b3867466d 100644 --- a/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts +++ b/aurora-serverless-v2-lambda-bedrock-cdk/lib/aurora-serverless-v2-lambda-bedrock-stack.ts @@ -9,8 +9,13 @@ export class AuroraServerlessV2LambdaBedrockStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); - // Use default VPC - const vpc = ec2.Vpc.fromLookup(this, "DefaultVpc", { isDefault: true }); + // VPC with isolated subnets for the database + const vpc = new ec2.Vpc(this, "Vpc", { + maxAzs: 2, + subnetConfiguration: [ + { name: "isolated", subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 24 }, + ], + }); // Aurora Serverless v2 cluster (PostgreSQL, scales to zero) const cluster = new rds.DatabaseCluster(this, "AuroraCluster", { @@ -21,8 +26,9 @@ export class AuroraServerlessV2LambdaBedrockStack extends cdk.Stack { serverlessV2MaxCapacity: 4, writer: rds.ClusterInstance.serverlessV2("writer"), vpc, - vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC }, + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, defaultDatabaseName: "appdb", + storageEncrypted: true, enableDataApi: true, removalPolicy: cdk.RemovalPolicy.DESTROY, }); @@ -73,7 +79,10 @@ export class AuroraServerlessV2LambdaBedrockStack extends cdk.Stack { queryFn.addToRolePolicy( new iam.PolicyStatement({ actions: ["bedrock:InvokeModel"], - resources: ["*"], + resources: [ + `arn:aws:bedrock:*:${this.account}:inference-profile/us.anthropic.claude-sonnet-4-20250514-v1:0`, + `arn:aws:bedrock:*::foundation-model/anthropic.claude-sonnet-4-20250514-v1:0`, + ], }) );