aws-cloudformation-lambda
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-lambda
Agent 安装分布
Skill 文档
AWS CloudFormation Lambda Serverless
Overview
Create production-ready serverless infrastructure using AWS CloudFormation templates. This skill covers Lambda functions, layers, event sources, API Gateway, Step Functions, cold start optimization, and best practices for parameters, outputs, and cross-stack references.
When to Use
Use this skill when:
- Creating new Lambda functions with CloudFormation
- Configuring Lambda layers for shared code
- Integrating Lambda with API Gateway (REST and HTTP API)
- Implementing event sources (SQS, SNS, EventBridge, S3, DynamoDB)
- Creating Step Functions with Lambda workflows
- Optimizing cold start and performance
- Organizing templates with Parameters, Outputs, Mappings, Conditions
- Implementing cross-stack references with export/import
- Using Transform for macros and reuse
CloudFormation Template Structure
Base Template with Standard Format
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda function with API Gateway integration
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Function Configuration
Parameters:
- FunctionName
- Runtime
- Handler
- Label:
default: Deployment Settings
Parameters:
- Environment
- DeployStage
Parameters:
FunctionName:
Type: String
Default: my-lambda-function
Description: Name of the Lambda function
Runtime:
Type: String
Default: python3.11
AllowedValues:
- python3.8
- python3.9
- python3.10
- python3.11
- nodejs18.x
- nodejs20.x
- java11
- java17
- java21
Handler:
Type: String
Default: index.handler
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
DeployStage:
Type: String
Default: dev
Mappings:
EnvironmentConfig:
dev:
MemorySize: 128
Timeout: 30
ReservedConcurrentExecutions: 5
staging:
MemorySize: 256
Timeout: 60
ReservedConcurrentExecutions: 20
production:
MemorySize: 512
Timeout: 120
ReservedConcurrentExecutions: 100
Conditions:
IsProduction: !Equals [!Ref Environment, production]
IsDev: !Equals [!Ref Environment, dev]
Transform:
- AWS::Serverless-2016-10-31
Resources:
# Lambda Function
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Ref FunctionName
Runtime: !Ref Runtime
Handler: !Ref Handler
Code:
S3Bucket: !Ref SourceBucket
S3Key: !Sub "lambda/${Environment}/function.zip"
MemorySize: !FindInMap [EnvironmentConfig, !Ref Environment, MemorySize]
Timeout: !FindInMap [EnvironmentConfig, !Ref Environment, Timeout]
Role: !GetAtt LambdaExecutionRole.Arn
Environment:
Variables:
ENVIRONMENT: !Ref Environment
LOG_LEVEL: !If [IsProduction, INFO, DEBUG]
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: !Ref ProjectName
Outputs:
LambdaFunctionArn:
Description: ARN of the Lambda function
Value: !GetAtt MyLambdaFunction.Arn
Export:
Name: !Sub "${AWS::StackName}-LambdaFunctionArn"
Best Practices for Parameters
AWS-Specific Parameter Types
Parameters:
# AWS-specific types for validation
VPCId:
Type: AWS::EC2::VPC::Id
Description: VPC where Lambda will run
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnets for Lambda VPC config
SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: Security groups for Lambda
LambdaRuntime:
Type: AWS::Lambda::Runtime
Description: Lambda runtime selection
IAMRoleArn:
Type: AWS::IAM::Role::Arn
Description: IAM role for Lambda execution
S3BucketForCode:
Type: AWS::S3::Bucket
Description: S3 bucket for Lambda code
KMSKeyArn:
Type: AWS::KMS::Key::Arn
Description: KMS key for environment variables
Parameter Constraints
Parameters:
FunctionName:
Type: String
Default: my-function
Description: Lambda function name
ConstraintDescription: Must be 1-64 characters, alphanumeric and hyphens
MinLength: 1
MaxLength: 64
AllowedPattern: "[a-zA-Z0-9-_]+"
MemorySize:
Type: Number
Default: 128
Description: Memory allocation in MB
MinValue: 128
MaxValue: 10240
ConstraintDescription: Must be between 128 and 10240 MB
Timeout:
Type: Number
Default: 30
Description: Function timeout in seconds
MinValue: 1
MaxValue: 900
ConstraintDescription: Must be between 1 and 900 seconds
EnvironmentName:
Type: String
Default: dev
Description: Deployment environment
AllowedValues:
- dev
- staging
- production
ConstraintDescription: Must be dev, staging, or production
SSM Parameter References
Parameters:
DatabaseConnectionString:
Type: AWS::SSM::Parameter::Value<String>
Default: /myapp/database/connection-string
Description: Database connection string from SSM
ApiKey:
Type: AWS::SSM::Parameter::Value<SecureString>
Default: /myapp/external-api/key
Description: API key from SSM Parameter Store
Outputs and Cross-Stack References
Export/Import Patterns
# Stack A - Network Stack
AWSTemplateFormatVersion: 2010-09-09
Description: Network infrastructure stack
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "${AWS::StackName}-vpc"
Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}-VPCId"
PublicSubnetIds:
Description: Public subnet IDs
Value: !Join [",", [!Ref PublicSubnet1, !Ref PublicSubnet2]]
Export:
Name: !Sub "${AWS::StackName}-PublicSubnetIds"
PrivateSubnetIds:
Description: Private subnet IDs
Value: !Join [",", [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub "${AWS::StackName}-PrivateSubnetIds"
LambdaSecurityGroupId:
Description: Security group ID for Lambda
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "${AWS::StackName}-LambdaSecurityGroupId"
# Stack B - Application Stack (imports from Stack A)
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda application stack
Parameters:
NetworkStackName:
Type: String
Default: network-stack
Description: Name of the network stack
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-processor"
Runtime: python3.11
Handler: index.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !GetAtt LambdaExecutionRole.Arn
VpcConfig:
SecurityGroupIds:
- !ImportValue
!Sub "${NetworkStackName}-LambdaSecurityGroupId"
SubnetIds:
- !Select [0, !Split [",", !ImportValue !Sub "${NetworkStackName}-PrivateSubnetIds"]]
- !Select [1, !Split [",", !ImportValue !Sub "${NetworkStackName}-PrivateSubnetIds"]]
Nested Stacks for Modularity
AWSTemplateFormatVersion: 2010-09-09
Description: Main stack with nested Lambda stacks
Resources:
# Nested stack for Lambda functions
LambdaFunctionsStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/lambda-functions.yaml
TimeoutInMinutes: 15
Parameters:
Environment: !Ref Environment
FunctionNamePrefix: !Ref FunctionNamePrefix
# Nested stack for API Gateway
ApiGatewayStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/api-gateway.yaml
TimeoutInMinutes: 15
Parameters:
Environment: !Ref Environment
LambdaFunctionArn: !GetAtt LambdaFunctionsStack.Outputs.FunctionArn
Lambda Functions with Advanced Configurations
Lambda Base with VPC and Environment
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda function with VPC, environment variables, and monitoring
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
VpcConfig:
Type: String
Default: full
AllowedValues:
- none
- full
- internal
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-lambda-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-vpc-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
- ec2:DescribeNetworkInterfaces
- ec2:DeleteNetworkInterface
Resource: "*"
- PolicyName: !Sub "${AWS::StackName}-secrets-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Ref SecretsArn
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-processor"
Runtime: python3.11
Handler: index.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: !Sub "lambda/${Environment}/function.zip"
MemorySize: 256
Timeout: 60
Role: !GetAtt LambdaExecutionRole.Arn
VpcConfig:
!If
- IsFullVpc
- SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
- !Ref AWS::NoValue
Environment:
Variables:
ENVIRONMENT: !Ref Environment
LOG_LEVEL: !If [IsProduction, INFO, DEBUG]
DB_HOST: !Ref DatabaseHost
DB_NAME: !Ref DatabaseName
TracingConfig:
Mode: !If [IsProduction, Active, PassThrough]
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
LambdaFunctionUrl:
Type: AWS::Lambda::Url
Properties:
AuthType: AWS_IAM
TargetFunctionArn: !GetAtt MyLambdaFunction.Arn
Cors:
AllowCredentials: true
AllowHeaders:
- "*"
AllowMethods:
- GET
- POST
AllowOrigins:
- !If [IsProduction, !Ref ProductionCorsOrigin, "*"]
MaxAge: 86400
Conditions:
IsFullVpc: !Equals [!Ref VpcConfig, full]
IsProduction: !Equals [!Ref Environment, production]
Lambda with Provisioned Concurrency
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-api"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/api.zip
MemorySize: 512
Timeout: 30
Role: !GetAtt LambdaExecutionRole.Arn
ProvisionedConcurrencyConfig:
Type: AWS::Lambda::ProvisionedConcurrencyConfig
Properties:
FunctionName: !Ref MyLambdaFunction
ProvisionedConcurrentExecutions: 5
ProvisionedExecutionTarget:
AllocationStrategy: PRICE_OPTIMIZED
Lambda Layers
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda function with layers
Resources:
CommonLibraryLayer:
Type: AWS::Lambda::LayerVersion
Properties:
LayerName: !Sub "${AWS::StackName}-common-lib"
Description: Common utilities for Lambda functions
Content:
S3Bucket: !Ref LayersBucket
S3Key: layers/common-lib.zip
CompatibleRuntimes:
- python3.9
- python3.10
- python3.11
CompatibleArchitectures:
- x86_64
- arm64
DataProcessingLayer:
Type: AWS::Lambda::LayerVersion
Properties:
LayerName: !Sub "${AWS::StackName}-data-processing"
Description: Data processing utilities
Content:
S3Bucket: !Ref LayersBucket
S3Key: layers/data-processing.zip
CompatibleRuntimes:
- python3.11
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-processor"
Runtime: python3.11
Handler: index.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/processor.zip
Layers:
- !Ref CommonLibraryLayer
- !Ref DataProcessingLayer
API Gateway Integration
API Gateway REST with Lambda Proxy
AWSTemplateFormatVersion: 2010-09-09
Description: API Gateway REST with Lambda proxy integration
Resources:
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub "${AWS::StackName}-api"
Description: REST API for Lambda backend
EndpointConfiguration:
Types:
- REGIONAL
MinimumCompressionSize: 1024
DisableExecuteApiEndpoint: false
ApiGatewayResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref ApiGatewayRestApi
ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
PathPart: items
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref ApiGatewayRestApi
ResourceId: !Ref ApiGatewayResource
HttpMethod: GET
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref ApiGatewayAuthorizer
RequestParameters:
method.request.querystring.id: true
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambdaFunction.Arn}/invocations"
IntegrationResponses:
- StatusCode: 200
ResponseParameters:
method.response.header.Access-Control-Allow-Origin: "'*'"
method.response.header.Content-Type: "'application/json'"
PassthroughBehavior: WHEN_NO_MATCH
MethodResponses:
- StatusCode: 200
ResponseModels:
application/json: Empty
ResponseParameters:
method.response.header.Access-Control-Allow-Origin: true
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: ApiGatewayMethod
Properties:
RestApiId: !Ref ApiGatewayRestApi
StageName: !Ref DeployStage
StageDescription:
LoggingLevel: !If [IsProduction, INFO, ERROR]
DataTraceEnabled: !If [IsProduction, false, true]
MetricsEnabled: true
ThrottlingRateLimit: 100
ThrottlingBurstLimit: 200
Variables:
Environment: !Ref Environment
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref MyLambdaFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/*/*"
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: !Sub "${AWS::StackName}-authorizer"
Type: COGNITO_USER_POOLS
RestApiId: !Ref ApiGatewayRestApi
ProviderARNs:
- !Ref CognitoUserPoolArn
IdentitySource: method.request.header.Authorization
AuthorizerResultTtlInSeconds: 300
Outputs:
ApiEndpoint:
Description: API Gateway endpoint URL
Value: !Sub "https://${ApiGatewayRestApi}.execute-api.${AWS::Region}.amazonaws.com/${DeployStage}/items"
API Gateway HTTP API with Lambda
Resources:
HttpApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: !Sub "${AWS::StackName}-http-api"
ProtocolType: HTTP
CorsConfiguration:
AllowOrigins:
- !If [IsProduction, !Ref ProductionDomain, "*"]
AllowMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
AllowHeaders:
- "*"
MaxAge: 86400
HttpApiStage:
Type: AWS::ApiGatewayV2::Stage
Properties:
ApiId: !Ref HttpApi
StageName: !Ref DeployStage
AutoDeploy: true
DefaultRouteSettings:
DetailedMetricsEnabled: true
ThrottlingBurstLimit: 100
ThrottlingRateLimit: 50
HttpApiIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref HttpApi
IntegrationType: AWS_PROXY
IntegrationUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambdaFunction.Arn}/invocations"
PayloadFormatVersion: "2.0"
HttpApiRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref HttpApi
RouteKey: ANY /items/{id}
Target: !Sub "integrations/${HttpApiIntegration.Id}"
Event Sources
SQS Event Source
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-sqs-processor"
Runtime: python3.11
Handler: sqs_handler.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/sqs-processor.zip
Timeout: 300
Role: !GetAtt LambdaExecutionRole.Arn
Queue:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${AWS::StackName}-queue"
VisibilityTimeout: 360
MessageRetentionPeriod: 1209600
RedrivePolicy:
deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
maxReceiveCount: 5
DeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${AWS::StackName}-dlq"
EventSourceMapping:
Type: AWS::Lambda::EventSourceMapping
Properties:
FunctionName: !Ref MyLambdaFunction
EventSourceArn: !GetAtt Queue.Arn
BatchSize: 10
MaximumBatchingWindowInSeconds: 60
ScalingConfig:
MaximumConcurrency: 10
FilterCriteria:
Filters:
- Pattern: '{"body": {"messageType": ["order", "notification"]}}'
Enabled: true
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-sqs-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaSQSQueueExecutionRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-dlq-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- sqs:DeleteMessage
- sqs:ReceiveMessage
Resource: !GetAtt DeadLetterQueue.Arn
SNS Event Source
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-sns-processor"
Runtime: python3.11
Handler: sns_handler.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/sns-processor.zip
Topic:
Type: AWS::SNS::Topic
Properties:
TopicName: !Sub "${AWS::StackName}-topic"
DisplayName: !Sub "${AWS::StackName} Notifications"
Subscription:
- Endpoint: !GetAtt MyLambdaFunction.Arn
Protocol: lambda
Tags:
- Key: Environment
Value: !Ref Environment
TopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
Topics:
- !Ref Topic
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: sns.amazonaws.com
Action: sns:Publish
Resource: !Ref Topic
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref MyLambdaFunction
Action: lambda:InvokeFunction
Principal: sns.amazonaws.com
SourceArn: !Ref Topic
EventBridge (CloudWatch Events)
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-scheduler"
Runtime: python3.11
Handler: scheduler.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/scheduler.zip
Timeout: 300
Role: !GetAtt LambdaExecutionRole.Arn
ScheduledRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${AWS::StackName}-scheduled-rule"
ScheduleExpression: "rate(5 minutes)"
State: ENABLED
Targets:
- Id: !Ref MyLambdaFunction
Arn: !GetAtt MyLambdaFunction.Arn
RetryPolicy:
MaximumEventAgeInSeconds: 86400
MaximumRetryAttempts: 3
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref MyLambdaFunction
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt ScheduledRule.Arn
S3 Event Source
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-s3-processor"
Runtime: python3.11
Handler: s3_handler.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/s3-processor.zip
Timeout: 300
Role: !GetAtt LambdaExecutionRole.Arn
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${AWS::StackName}-uploads-${AWS::AccountId}-${AWS::Region}"
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
VersioningConfiguration:
Status: Enabled
NotificationConfiguration:
LambdaConfigurations:
- Event: s3:ObjectCreated:*
Filter:
S3Key:
Rules:
- Name: suffix
Value: .csv
Function: !GetAtt MyLambdaFunction.Arn
- Event: s3:ObjectCreated:*
Filter:
S3Key:
Rules:
- Name: prefix
Value: processed/
Function: !GetAtt MyLambdaFunction.Arn
LambdaPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref MyLambdaFunction
Action: lambda:InvokeFunction
Principal: s3.amazonaws.com
SourceArn: !GetAtt Bucket.Arn
Step Functions Integration
AWSTemplateFormatVersion: 2010-09-09
Description: Step Functions with Lambda tasks
Resources:
# Lambda functions for Step Functions
ProcessItemFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-process-item"
Runtime: python3.11
Handler: process_item.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/process-item.zip
Timeout: 300
Role: !GetAtt LambdaExecutionRole.Arn
ValidateItemFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-validate-item"
Runtime: python3.11
Handler: validate_item.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/validate-item.zip
Timeout: 60
Role: !GetAtt LambdaExecutionRole.Arn
NotifyCompletionFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-notify-completion"
Runtime: python3.11
Handler: notify.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/notify.zip
Timeout: 60
Role: !GetAtt LambdaExecutionRole.Arn
# Step Functions State Machine
ProcessingStateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
StateMachineName: !Sub "${AWS::StackName}-processor"
StateMachineType: STANDARD
DefinitionString: !Sub |
{
"Comment": "Item processing state machine",
"StartAt": "ValidateItem",
"States": {
"ValidateItem": {
"Type": "Task",
"Resource": "${ValidateItemFunction.Arn}",
"Retry": [
{
"ErrorEquals": ["States.TaskFailed"],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Next": "ProcessItem"
},
"ProcessItem": {
"Type": "Task",
"Resource": "${ProcessItemFunction.Arn}",
"Retry": [
{
"ErrorEquals": ["States.TaskFailed"],
"IntervalSeconds": 5,
"MaxAttempts": 2,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Next": "HandleFailure"
}
],
"Next": "NotifyCompletion"
},
"NotifyCompletion": {
"Type": "Task",
"Resource": "${NotifyCompletionFunction.Arn}",
"End": true
},
"HandleFailure": {
"Type": "Pass",
"End": true
}
}
}
RoleArn: !GetAtt StepFunctionsExecutionRole.Arn
LoggingConfiguration:
Level: ALL
IncludeExecutionData: true
Destinations:
- CloudWatchLogsLogGroup: !Ref StateMachineLogGroup
StepFunctionsExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-sfn-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: states.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: !Sub "${AWS::StackName}-lambda-invoke"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource:
- !GetAtt ProcessItemFunction.Arn
- !GetAtt ValidateItemFunction.Arn
- !GetAtt NotifyCompletionFunction.Arn
StateMachineLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/state-machine/${AWS::StackName}"
RetentionInDays: 30
Cold Start Optimization
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda function optimized for cold start
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
Resources:
# Use AWS::Serverless::Function for better cold start
OptimizedLambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-optimized"
CodeUri: s3://bucket/function.zip
Handler: app.handler
Runtime: python3.11
MemorySize: 512
Timeout: 30
EphemeralStorage:
Size: 1024
SnapStart:
ApplyOn: PublishedVersions
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: !If [IsProduction, 5, 0]
Layers:
- !Ref CommonDependenciesLayer
Environment:
Variables:
PYTHONPATH: "/var/task:/opt"
Policies:
- AWSLambdaVPCAccessExecutionRole
- AmazonS3ReadOnlyAccess
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds: !Ref PrivateSubnetIds
EventInvokeConfig:
MaximumEventAgeInSeconds: 3600
MaximumRetryAttempts: 2
# Optimized layer with pre-installed dependencies
CommonDependenciesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: !Sub "${AWS::StackName}-dependencies"
Description: Pre-installed Python dependencies for Lambda
ContentUri: s3://bucket/layers/dependencies.zip
CompatibleRuntimes:
- python3.11
CompatibleArchitectures:
- x86_64
RetentionPolicy: Retain
Conditions:
IsProduction: !Equals [!Ref Environment, production]
Outputs:
FunctionArn:
Description: Lambda function ARN
Value: !GetAtt OptimizedLambdaFunction.Arn
FunctionUrl:
Description: Lambda function URL for direct invocation
Value: !GetAtt OptimizedLambdaFunction.Url
Monitoring and Logging
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda with comprehensive monitoring
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-monitored"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !GetAtt LambdaExecutionRole.Arn
TracingConfig:
Mode: Active
# Log group with retention
LambdaLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/lambda/${AWS::StackName}-monitored"
RetentionInDays: 30
KmsKeyId: !Ref LogKmsKey
# Metric filter for errors
ErrorMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref LambdaLogGroup
FilterPattern: 'ERROR'
MetricTransformations:
- MetricValue: "1"
MetricNamespace: !Sub "${AWS::StackName}/Lambda"
MetricName: ErrorCount
# CloudWatch Alarms
HighErrorRateAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub "${AWS::StackName}-high-error-rate"
AlarmDescription: Alert when error rate exceeds threshold
MetricName: Errors
Namespace: AWS/Lambda
Dimensions:
- Name: FunctionName
Value: !Ref MyLambdaFunction
Statistic: Sum
Period: 60
EvaluationPeriods: 5
Threshold: 10
ComparisonOperator: GreaterThanThreshold
AlarmActions:
- !Ref AlertTopic
HighThrottlesAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub "${AWS::StackName}-high-throttles"
AlarmDescription: Alert when throttling occurs
MetricName: Throttles
Namespace: AWS/Lambda
Dimensions:
- Name: FunctionName
Value: !Ref MyLambdaFunction
Statistic: Sum
Period: 60
EvaluationPeriods: 3
Threshold: 5
ComparisonOperator: GreaterThanThreshold
AlertTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: !Sub "${AWS::StackName}-alerts"
# Lambda Destination for async invocations
LambdaDestination:
Type: AWS::Lambda::EventInvokeConfig
Properties:
FunctionName: !Ref MyLambdaFunction
MaximumEventAgeInSeconds: 3600
MaximumRetryAttempts: 2
Qualifier: $LATEST
Conditions and Transform
Conditions for Environment-Specific Resources
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda with conditional resources
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
Description: Deployment environment
Conditions:
IsProduction: !Equals [!Ref Environment, production]
IsStaging: !Equals [!Ref Environment, staging]
CreateDeadLetterQueue: !Or [!Equals [!Ref Environment, staging], !Equals [!Ref Environment, production]]
EnableXray: !Not [!Equals [!Ref Environment, dev]]
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-function"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: !Sub "lambda/${Environment}/function.zip"
Timeout: !If [IsProduction, 60, 30]
MemorySize: !If [IsProduction, 512, 256]
Role: !GetAtt LambdaExecutionRole.Arn
TracingConfig: !If
- EnableXray
- Mode: Active
- !Ref AWS::NoValue
Environment:
Variables:
LOG_LEVEL: !If [IsProduction, INFO, DEBUG]
DeadLetterQueue:
Type: AWS::SQS::Queue
Condition: CreateDeadLetterQueue
Properties:
QueueName: !Sub "${AWS::StackName}-dlq"
Transform for Code Reuse
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: Using SAM Transform for Lambda
Globals:
Function:
Timeout: 30
Runtime: python3.11
Tracing: Active
Environment:
Variables:
LOG_LEVEL: INFO
Metadata:
DockerBuild: true
Dockerfile: Dockerfile
DockerContext: lambda_function/
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-sam-function"
Handler: app.handler
CodeUri: lambda_function/
Policies:
- S3ReadPolicy:
BucketName: !Ref DataBucket
- DynamoDBReadPolicy:
TableName: !Ref DataTable
Events:
Api:
Type: Api
Properties:
Path: /items
Method: get
SqsQueue:
Type: SQS
Properties:
Queue: !GetAtt Queue.Arn
BatchSize: 10
AutoPublishAlias: !Ref Environment
DeploymentPreference:
Type: !Ref DeploymentConfig
Alarms:
- !Ref ErrorAlarm
- !Ref LatencyAlarm
DataTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: !Sub "${AWS::StackName}-table"
PrimaryKey:
Name: id
Type: String
Parameters:
Environment:
Type: String
Default: dev
DeploymentConfig:
Type: String
Default: AllAtOnce
AllowedValues:
- Canary10Percent5Minutes
- Canary10Percent10Minutes
- Canary10Percent15Minutes
- AllAtOnce
- Linear10PercentEvery1Minute
- Linear10PercentEvery2Minutes
- Linear10PercentEvery3Minutes
Best Practices
Security
- Use IAM roles with minimum necessary permissions
- Encrypt environment variables with KMS
- Use VPC for private resource access
- Configure resource-based policies for invocations
- Enable AWS WAF for API Gateway protection
- Use API keys and throttling for protection
Performance
- Choose memory size based on profiling
- Use provisioned concurrency for critical latency
- Optimize package size for cold start
- Use layers for shared dependencies
- Pre-compile code for interpreted languages
- Consider SnapStart for Java/.NET
Monitoring
- Enable detailed metrics and tracing
- Configure appropriate log retention
- Create alarms for errors and throttling
- Use Lambda destinations for async error handling
- Implement distributed tracing
Deployment
- Use change sets before deployment
- Test templates with cfn-lint
- Organize stacks by lifecycle and ownership
- Use nested stacks for modularity
- Implement blue/green deployments
CloudFormation Stack Management Best Practices
Stack Policies
Stack policies protect stack resources from unintentional updates that could cause critical changes or deletions.
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
# Function configuration
# Stack policy to protect Lambda function from updates
StackPolicy:
Type: AWS::CloudFormation::StackPolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal: "*"
Action: "Update:*"
Resource: "*"
- Effect: Deny
Principal: "*"
Action:
- Update:Replace
- Update:Delete
Resource:
- LogicalId: LambdaFunction
ResourceType: AWS::Lambda::Function
Condition:
StringEquals:
ResourceAttribute: Arn:
Fn::Ref: LambdaFunction
Termination Protection
Enable termination protection to prevent accidental stack deletion, especially for production environments.
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda function with termination protection
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-function"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !GetAtt LambdaExecutionRole.Arn
# Enable termination protection (must be set during stack creation)
# This is a stack-level attribute, not a resource
Important: Termination protection must be enabled during stack creation via AWS Console, CLI, or API:
aws cloudformation create-stack \
--stack-name my-lambda-stack \
--template-body file://template.yaml \
--enable-termination-protection \
--capabilities CAPABILITY_IAM
Drift Detection
Detect when infrastructure has diverged from the CloudFormation template.
Resources:
# All Lambda resources support drift detection
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-function"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !GetAtt LambdaExecutionRole.Arn
Environment:
Variables:
ENVIRONMENT: !Ref Environment
LOG_LEVEL: !Ref LogLevel
CLI commands for drift detection:
# Detect drift on a stack
aws cloudformation detect-drift --stack-name my-lambda-stack
# Get drift detection status
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <detection-id>
# Get resource drift status
aws cloudformation describe-stack-resource-drifts \
--stack-name my-lambda-stack
# Compare actual vs expected resource properties
aws cloudformation get-stack-policy --stack-name my-lambda-stack
Change Sets
Use change sets to preview and review stack changes before execution.
Resources:
MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-function"
Runtime: python3.11
Handler: app.handler
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/function.zip
Role: !GetAtt LambdaExecutionRole.Arn
MemorySize: !Ref MemorySize
Timeout: !Ref Timeout
Parameters:
MemorySize:
Type: Number
Default: 256
Description: Memory allocation in MB
Timeout:
Type: Number
Default: 30
Description: Function timeout in seconds
Change set workflow:
# 1. Create a change set
aws cloudformation create-change-set \
--stack-name my-lambda-stack \
--change-set-name my-changeset \
--template-body file://template.yaml \
--capabilities CAPABILITY_IAM \
--parameters ParameterKey=MemorySize,ParameterValue=512
# 2. Describe the change set to review changes
aws cloudformation describe-change-set \
--stack-name my-lambda-stack \
--change-set-name my-changeset
# 3. Execute the change set
aws cloudformation execute-change-set \
--stack-name my-lambda-stack \
--change-set-name my-changeset
# Or delete if changes are not acceptable
aws cloudformation delete-change-set \
--stack-name my-lambda-stack \
--change-set-name my-changeset
Change set types:
CREATE: For new stacksUPDATE: For existing stacksIMPORT: For importing existing resources
Related Resources
Additional Files
For complete details on resources and their properties, see:
- REFERENCE.md – Detailed reference guide for all CloudFormation resources
- EXAMPLES.md – Complete production-ready examples