Skip to content

Commit 44183ff

Browse files
authored
Merge pull request #2883 from DmitryGulin/pattern/durable-lambda-on-capacity-provider
add lambda-durable-managed-instances-cdk pattern
2 parents 5f8bec7 + 01660ab commit 44183ff

13 files changed

Lines changed: 763 additions & 0 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
5+
6+
# CDK asset staging directory
7+
.cdk.staging
8+
cdk.out
9+
cdk.context.json
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# AWS Lambda durable functions on AWS Lambda Managed Instances
2+
3+
This pattern demonstrates how to implement AWS Lambda durable functions running on AWS Lambda Managed Instances using AWS CDK. AWS Lambda durable functions allow Lambda functions to maintain state and execution context across multiple invocations, while AWS Lambda Managed Instances provide predictable performance and reduced cold starts.
4+
5+
Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/lambda-durable-managed-instances-cdk
6+
7+
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.
8+
9+
**Note**: AWS Lambda Managed Instances provision EC2 instances that are **NOT eligible for the AWS Free Tier**. These instances will incur charges immediately upon deployment, regardless of your Free Tier status.
10+
11+
## Requirements
12+
13+
* [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.
14+
* [AWS CLI v2](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) (latest available version) installed and configured
15+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
16+
* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) (version 2.232.0 or later) installed and configured
17+
* [Node.js](https://nodejs.org/) (version 24.x or later)
18+
19+
## Deployment Instructions
20+
21+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
22+
```
23+
git clone https://github.com/aws-samples/serverless-patterns
24+
```
25+
1. Change directory to the pattern directory:
26+
```
27+
cd lambda-durable-managed-instances-cdk
28+
```
29+
1. Install the project dependencies:
30+
```
31+
npm install
32+
```
33+
1. Build the project:
34+
```
35+
npm run build
36+
```
37+
1. Deploy the CDK stack:
38+
```
39+
npx cdk deploy
40+
```
41+
Note: This stack is currently configured to deploy to the `us-east-2` region. Please refer to the [AWS capabilities explorer](https://builder.aws.com/build/capabilities/explore) for feature availability in your desired region.
42+
43+
1. Note the outputs from the AWS CDK deployment process. These contain the resource names and/or ARNs which are used for testing.
44+
45+
## How it works
46+
47+
This pattern demonstrates the integration of two key Lambda features:
48+
49+
### AWS Lambda durable functions
50+
[AWS Lambda durable functions](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html) enable Lambda functions to maintain state and execution context across multiple invocations. This allows for:
51+
- Long-running workflows that can span multiple function invocations
52+
- State persistence between executions
53+
- Improved reliability for complex processing tasks
54+
- Better handling of timeouts and retries
55+
56+
### AWS Lambda Managed Instances
57+
[AWS Lambda Managed Instances](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances.html) provide:
58+
- Predictable performance with pre-warmed execution environments
59+
- Reduced cold start latency
60+
- Consistent execution characteristics
61+
- Better resource utilization for frequently invoked functions
62+
63+
The combination of these features allows for building robust, stateful serverless applications that can handle complex workflows while maintaining high performance and reliability.
64+
65+
## Testing
66+
67+
After deployment, you can test the AWS Lambda durable function using the provided test script, AWS CLI, or AWS Console.
68+
69+
### Automated Testing Script
70+
71+
The pattern includes a comprehensive test script that demonstrates all aspects of durable function execution:
72+
73+
1. **Make the test script executable and run it**:
74+
```bash
75+
chmod +x test-lambda.sh
76+
./test-lambda.sh [profile] [region]
77+
```
78+
79+
Examples:
80+
```bash
81+
# Using default AWS profile and region
82+
./test-lambda.sh
83+
84+
# Using specific profile and region
85+
./test-lambda.sh my-profile us-west-2
86+
```
87+
88+
2. **What the script does**:
89+
- Invokes the function asynchronously with a test payload
90+
- Extracts the durable execution ARN from the response
91+
- Shows real-time execution history with step details
92+
- Displays CloudWatch logs with execution flow
93+
- Retrieves the final execution result with input/output JSON
94+
- Provides helpful CLI commands for manual inspection
95+
96+
3. **Script output includes**:
97+
- Function invocation status and durable execution ARN
98+
- Step-by-step execution history showing the step-wait-step pattern
99+
- Detailed logs with business logic tracing
100+
- Final execution result with timestamps and processed data
101+
102+
### Manual AWS CLI Testing
103+
104+
#### Basic Function Invocation
105+
106+
1. **Synchronous invocation** (for immediate response):
107+
```bash
108+
aws lambda invoke \
109+
--function-name step-wait-step-durable-function \
110+
--payload file://events/basic-order.json \
111+
--cli-binary-format raw-in-base64-out \
112+
--region us-east-2 \
113+
response.json
114+
```
115+
116+
2. **Asynchronous invocation** (recommended for durable functions):
117+
```bash
118+
aws lambda invoke \
119+
--function-name step-wait-step-durable-function:$LATEST.PUBLISHED \
120+
--invocation-type Event \
121+
--payload file://events/basic-order.json \
122+
--cli-binary-format raw-in-base64-out \
123+
--region us-east-2 \
124+
response.json
125+
```
126+
127+
#### Monitoring Durable Execution
128+
129+
After invoking the function asynchronously, you'll receive a durable execution ARN. Use these commands to monitor the execution:
130+
131+
1. **Get execution details and result**:
132+
```bash
133+
aws lambda get-durable-execution \
134+
--durable-execution-arn "YOUR_EXECUTION_ARN" \
135+
--region us-east-2
136+
```
137+
138+
2. **View execution history** (step-by-step flow):
139+
```bash
140+
aws lambda get-durable-execution-history \
141+
--durable-execution-arn "YOUR_EXECUTION_ARN" \
142+
--region us-east-2
143+
```
144+
145+
3. **List all executions for the function**:
146+
```bash
147+
aws lambda list-durable-executions-by-function \
148+
--function-name step-wait-step-durable-function \
149+
--region us-east-2
150+
```
151+
152+
4. **View CloudWatch logs**:
153+
```bash
154+
aws logs filter-log-events \
155+
--log-group-name /aws/lambda/step-wait-step-durable-function \
156+
--start-time $(date -d '5 minutes ago' +%s)000 \
157+
--region us-east-2 \
158+
--filter-pattern 'INFO'
159+
```
160+
161+
### AWS Console Testing
162+
163+
1. Navigate to the Lambda service in the AWS Console
164+
2. Find the function named `step-wait-step-durable-function`
165+
3. Create a test event using the payload from `events/basic-order.json` or create a custom payload with:
166+
```json
167+
{
168+
"orderId": "your-test-order-id"
169+
}
170+
```
171+
4. Execute the test and observe the results in the execution logs
172+
173+
### Expected Behavior
174+
175+
The function demonstrates the **step-wait-step pattern** with durable execution:
176+
177+
1. **Step 1 - Validate Order**:
178+
- Processes the input order ID
179+
- Returns validation status with timestamp
180+
- Logs: "Validating order [orderId]"
181+
182+
2. **Wait Phase - 5 Second Delay**:
183+
- Durable wait without consuming execution time
184+
- Function execution pauses and resumes automatically
185+
- Logs: "Order validated, waiting 5 seconds before processing"
186+
187+
3. **Step 2 - Process Order**:
188+
- Final processing with completion timestamp
189+
- Returns processed order with both validation and processing timestamps
190+
- Logs: "Processing order [orderId]" and "Step-wait-step execution completed"
191+
192+
### Sample Output
193+
194+
**Execution History** shows the durable execution flow:
195+
```
196+
ExecutionStarted → StepStarted (validate-order) → StepSucceeded →
197+
WaitStarted (wait 5s) → WaitSucceeded → StepStarted (process-order) →
198+
StepSucceeded → ExecutionSucceeded
199+
```
200+
201+
**Final Result** contains the processed order data:
202+
```json
203+
{
204+
"orderId": "order-123",
205+
"status": "processed",
206+
"validatedAt": 1765404928643,
207+
"processedAt": 1765404934023
208+
}
209+
```
210+
211+
### Monitoring and Observability
212+
213+
Monitor the execution through multiple channels:
214+
- **CloudWatch Logs**: Detailed execution flow and business logic tracing
215+
- **Durable Execution History**: Step-by-step execution events with timestamps
216+
- **Lambda Metrics**: Function performance and invocation statistics
217+
- **Execution State**: Real-time status and result data via AWS CLI
218+
219+
## Regional Availability
220+
221+
This stack is configured to deploy to the `us-east-2` region. Before deploying to a different region, please verify that both AWS Lambda durable functions and AWS Lambda Managed Instances features are available in your target region by using the [AWS capabilities explorer](https://builder.aws.com/build/capabilities/explore) or consulting the official AWS documentation:
222+
223+
- [AWS Lambda durable functions documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
224+
- [AWS Lambda Managed Instances documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances.html)
225+
226+
## Cleanup
227+
228+
1. Delete the stack
229+
```bash
230+
npx cdk destroy
231+
```
232+
1. Confirm the stack has been deleted by checking the AWS CloudFormation console or running:
233+
```bash
234+
aws cloudformation describe-stacks --stack-name lambda-durable-functions-managed-instances --region us-east-2
235+
```
236+
237+
----
238+
Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
239+
240+
SPDX-License-Identifier: MIT-0
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env node
2+
import { App } from 'aws-cdk-lib/core';
3+
import { DemoStack } from '../lib/demo-stack';
4+
5+
const app = new App();
6+
new DemoStack(app, 'LambdaDurableFunctionsManagedInstancesDemo', {
7+
stackName: 'lambda-durable-functions-managed-instances',
8+
env: {
9+
account: process.env.CDK_DEFAULT_ACCOUNT,
10+
region: process.env.CDK_DEFAULT_REGION ?? 'us-east-2',
11+
},
12+
description: 'POC stack demonstrating AWS Lambda durable functions running on AWS Lambda Managed Instances',
13+
});
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/app.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-signer:signingProfileNamePassedToCfn": true,
21+
"@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": true,
22+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
23+
"@aws-cdk/core:checkSecretUsage": true,
24+
"@aws-cdk/core:target-partitions": [
25+
"aws",
26+
"aws-cn"
27+
],
28+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
29+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
30+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
31+
"@aws-cdk/aws-iam:minimizePolicies": true,
32+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
33+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
34+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
35+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
36+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
37+
"@aws-cdk/core:enablePartitionLiterals": true,
38+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
39+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
40+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
41+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
42+
"@aws-cdk/aws-route53-patters:useCertificate": true,
43+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
44+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
45+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
46+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
47+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
48+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
49+
"@aws-cdk/aws-redshift:columnId": true,
50+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
51+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
52+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
53+
"@aws-cdk/aws-kms:aliasNameRef": true,
54+
"@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": true,
55+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
56+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
57+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
58+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
59+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
60+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
61+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
62+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
63+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
64+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
65+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
66+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
67+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
68+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
69+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
70+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
71+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
72+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
73+
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
74+
"@aws-cdk/core:explicitStackTags": true,
75+
"@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false,
76+
"@aws-cdk/aws-ecs:disableEcsImdsBlocking": true,
77+
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
78+
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
79+
"@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true,
80+
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
81+
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
82+
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
83+
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
84+
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true,
85+
"@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true,
86+
"@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true,
87+
"@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true,
88+
"@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true,
89+
"@aws-cdk/core:enableAdditionalMetadataCollection": true,
90+
"@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": false,
91+
"@aws-cdk/aws-s3:setUniqueReplicationRoleName": true,
92+
"@aws-cdk/aws-events:requireEventBusPolicySid": true,
93+
"@aws-cdk/core:aspectPrioritiesMutating": true,
94+
"@aws-cdk/aws-dynamodb:retainTableReplica": true,
95+
"@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": true,
96+
"@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": true,
97+
"@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true,
98+
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true,
99+
"@aws-cdk/aws-lambda:useCdkManagedLogGroup": true
100+
}
101+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"orderId": "order-123"
3+
}

0 commit comments

Comments
 (0)