tessl install github:giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-lambdagithub.com/giuseppe-trisciuoglio/developer-kit
AWS CloudFormation patterns for Lambda functions, layers, event sources, and integrations. Use when creating Lambda functions with CloudFormation, configuring API Gateway, Step Functions, EventBridge, SQS, SNS triggers, and implementing template structure with Parameters, Outputs, Mappings, Conditions, cross-stack references, and best practices for cold start optimization.
Review Score
83%
Validation Score
10/16
Implementation Score
73%
Activation Score
100%
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.
Use this skill when:
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"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 variablesParameters:
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 productionParameters:
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# 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"]]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.FunctionArnAWSTemplateFormatVersion: 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]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_OPTIMIZEDAWSTemplateFormatVersion: 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 DataProcessingLayerAWSTemplateFormatVersion: 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"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}"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.ArnResources:
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 TopicResources:
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.ArnResources:
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.ArnAWSTemplateFormatVersion: 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: 30AWSTemplateFormatVersion: 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.UrlAWSTemplateFormatVersion: 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: $LATESTAWSTemplateFormatVersion: 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"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
- Linear10PercentEvery3MinutesStack 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: LambdaFunctionEnable 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 resourceImportant: 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_IAMDetect 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 LogLevelCLI 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-stackUse 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 secondsChange 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-changesetChange set types:
CREATE: For new stacksUPDATE: For existing stacksIMPORT: For importing existing resourcesFor complete details on resources and their properties, see: