home / skills / giuseppe-trisciuoglio / developer-kit / aws-cloudformation-auto-scaling

This skill helps you create production-ready Auto Scaling infrastructure with CloudFormation for EC2, ECS, and Lambda, optimizing availability and cost.

npx playbooks add skill giuseppe-trisciuoglio/developer-kit --skill aws-cloudformation-auto-scaling

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
41.3 KB
---
name: aws-cloudformation-auto-scaling
description: Provides AWS CloudFormation patterns for Auto Scaling including EC2, ECS, and Lambda. Use when creating Auto Scaling groups, launch configurations, launch templates, scaling policies, lifecycle hooks, and predictive scaling. Covers template structure with Parameters, Outputs, Mappings, Conditions, cross-stack references, and best practices for high availability and cost optimization.
category: aws
tags: [aws, cloudformation, auto-scaling, ec2, ecs, lambda, infrastructure, iaac, scaling]
version: 1.1.0
allowed-tools: Read, Write, Bash
---

# AWS CloudFormation Auto Scaling

## Overview

Create production-ready Auto Scaling infrastructure using AWS CloudFormation templates. This skill covers Auto Scaling Groups for EC2, ECS, and Lambda, launch configurations, launch templates, scaling policies, lifecycle hooks, and best practices for high availability and cost optimization.

## When to Use

Use this skill when:
- Creating Auto Scaling Groups for EC2 instances
- Configuring Launch Configurations or Launch Templates
- Implementing scaling policies (step, target tracking, simple)
- Adding lifecycle hooks for lifecycle management
- Creating scaling for ECS services
- Implementing Lambda provisioned concurrency scaling
- Organizing templates with Parameters, Outputs, Mappings, Conditions
- Implementing cross-stack references with export/import
- Using mixed instances policies for diversity

## Instructions

Follow these steps to create Auto Scaling infrastructure with CloudFormation:

1. **Define Parameters**: Use AWS-specific parameter types for validation (e.g., `AWS::EC2::Image::Id`)
2. **Configure Launch Resources**: Create LaunchConfiguration or LaunchTemplate with proper instance settings
3. **Create Auto Scaling Group**: Specify min/max/desired capacity and associate with launch resource
4. **Add Scaling Policies**: Implement target tracking, step, or simple scaling policies
5. **Configure Health Checks**: Set up ELB or EC2 health checks with appropriate grace periods
6. **Add Lifecycle Hooks**: Implement hooks for custom actions during instance lifecycle
7. **Set Up Monitoring**: Configure CloudWatch alarms for scaling triggers
8. **Use Cross-Stack References**: Export ASG names and ARNs for other stacks to import

For complete examples, see the [EXAMPLES.md](references/examples.md) file.

## CloudFormation Template Structure

### Base Template with Standard Format

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling group with load balancer

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Auto Scaling Configuration
        Parameters:
          - MinSize
          - MaxSize
          - DesiredCapacity
      - Label:
          default: Instance Configuration
        Parameters:
          - InstanceType
          - AmiId

Parameters:
  MinSize:
    Type: Number
    Default: 2
    Description: Minimum number of instances

  MaxSize:
    Type: Number
    Default: 10
    Description: Maximum number of instances

  DesiredCapacity:
    Type: Number
    Default: 2
    Description: Desired number of instances

  InstanceType:
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.micro
      - t3.small
      - t3.medium
      - t3.large

  AmiId:
    Type: AWS::EC2::Image::Id
    Description: AMI ID for instances

Mappings:
  EnvironmentConfig:
    dev:
      InstanceType: t3.micro
      MinSize: 1
      MaxSize: 3
    staging:
      InstanceType: t3.medium
      MinSize: 2
      MaxSize: 6
    production:
      InstanceType: t3.large
      MinSize: 3
      MaxSize: 12

Conditions:
  IsProduction: !Equals [!Ref Environment, production]
  UseSpotInstances: !Or [!Equals [!Ref Environment, dev], !Equals [!Ref Environment, staging]]

Resources:
  # Auto Scaling Group
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: !Ref MinSize
      MaxSize: !Ref MaxSize
      DesiredCapacity: !Ref DesiredCapacity
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration
      LoadBalancerNames:
        - !Ref MyLoadBalancer
      HealthCheckType: ELB
      HealthCheckGracePeriod: 300
      TerminationPolicies:
        - OldestInstance
        - Default
      Tags:
        - Key: Environment
          Value: !Ref Environment
          PropagateAtLaunch: true
        - Key: ManagedBy
          Value: CloudFormation
          PropagateAtLaunch: true

Outputs:
  AutoScalingGroupName:
    Description: Name of the Auto Scaling Group
    Value: !Ref MyAutoScalingGroup
```

## Parameters Best Practices

### AWS-Specific Parameter Types

```yaml
Parameters:
  # AWS-specific types for validation
  InstanceType:
    Type: AWS::EC2::Instance::Type
    Description: EC2 instance type

  AmiId:
    Type: AWS::EC2::Image::Id
    Description: AMI ID for instances

  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: Subnets for Auto Scaling group

  SecurityGroupIds:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: Security groups for instances

  LoadBalancerArn:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer::Arn
    Description: Application Load Balancer ARN

  TargetGroupArn:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup::Arn
    Description: Target Group ARN for ALB

  LaunchTemplateId:
    Type: AWS::EC2::LaunchTemplate::LaunchTemplateId
    Description: Launch template ID

  ScalingPolicyArn:
    Type: AWS::AutoScaling::ScalingPolicy::Arn
    Description: Scaling policy ARN
```

### Parameter Constraints

```yaml
Parameters:
  MinSize:
    Type: Number
    Default: 1
    Description: Minimum number of instances
    MinValue: 0
    MaxValue: 1000
    ConstraintDescription: Must be between 0 and 1000

  MaxSize:
    Type: Number
    Default: 10
    Description: Maximum number of instances
    MinValue: 1
    MaxValue: 1000
    ConstraintDescription: Must be between 1 and 1000

  DesiredCapacity:
    Type: Number
    Default: 2
    Description: Desired number of instances
    MinValue: 0
    MaxValue: 1000

  InstanceType:
    Type: String
    Default: t3.micro
    Description: EC2 instance type
    ConstraintDescription: Must be a valid EC2 instance type

  AmiId:
    Type: AWS::EC2::Image::Id
    Description: AMI ID

  EnvironmentName:
    Type: String
    Default: dev
    Description: Deployment environment
    AllowedValues:
      - dev
      - staging
      - production
    ConstraintDescription: Must be dev, staging, or production
```

### SSM Parameter References

```yaml
Parameters:
  LatestAmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
    Description: Latest Amazon Linux 2 AMI from SSM

  InstanceConfiguration:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /myapp/instance-configuration
    Description: Instance configuration from SSM
```

## Outputs and Cross-Stack References

### Export/Import Patterns

```yaml
# Stack A - Network and Auto Scaling Stack
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling infrastructure stack

Resources:
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration

Outputs:
  AutoScalingGroupName:
    Description: Name of the Auto Scaling Group
    Value: !Ref MyAutoScalingGroup
    Export:
      Name: !Sub "${AWS::StackName}-AutoScalingGroupName"

  AutoScalingGroupArn:
    Description: ARN of the Auto Scaling Group
    Value: !Sub "arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/${MyAutoScalingGroup}"
    Export:
      Name: !Sub "${AWS::StackName}-AutoScalingGroupArn"

  LaunchConfigurationName:
    Description: Name of the Launch Configuration
    Value: !Ref MyLaunchConfiguration
    Export:
      Name: !Sub "${AWS::StackName}-LaunchConfigurationName"
```

```yaml
# Stack B - Application Stack (imports from Stack A)
AWSTemplateFormatVersion: 2010-09-09
Description: Application stack using Auto Scaling from infrastructure stack

Parameters:
  InfraStackName:
    Type: String
    Default: infra-stack
    Description: Name of the infrastructure stack

Resources:
  ScalingPolicy:
    Type: AWS::AutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-scale-up"
      PolicyType: StepScaling
      AdjustmentType: PercentChangeInCapacity
      Cooldown: 300
      StepAdjustments:
        - MetricIntervalLowerBound: 0
          MetricIntervalUpperBound: 10000
          ScalingAdjustment: 200
        - MetricIntervalLowerBound: 10000
          ScalingAdjustment: 400
      AutoScalingGroupName: !ImportValue
        !Sub "${InfraStackName}-AutoScalingGroupName"
```

### Nested Stacks for Modularity

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Main stack with nested Auto Scaling stacks

Resources:
  # Nested stack for EC2 Auto Scaling
  EC2AutoScalingStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/bucket/ec2-asg.yaml
      TimeoutInMinutes: 15
      Parameters:
        Environment: !Ref Environment
        InstanceType: !Ref InstanceType
        MinSize: !Ref MinSize
        MaxSize: !Ref MaxSize

  # Nested stack for scaling policies
  ScalingPoliciesStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.amazonaws.com/bucket/scaling-policies.yaml
      TimeoutInMinutes: 15
      Parameters:
        AutoScalingGroupName: !GetAtt EC2AutoScalingStack.Outputs.AutoScalingGroupName
        Environment: !Ref Environment
```

## Launch Configurations

### Base Launch Configuration

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with Launch Configuration

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro

  AmiId:
    Type: AWS::EC2::Image::Id

  KeyName:
    Type: AWS::EC2::KeyPair::KeyName

Resources:
  MyLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      LaunchConfigurationName: !Sub "${AWS::StackName}-lc"
      ImageId: !Ref AmiId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      SecurityGroups:
        - !Ref InstanceSecurityGroup
      InstanceMonitoring: Enabled
      SpotPrice: !If [UseSpot, "0.05", !Ref AWS::NoValue]
      UserData:
        Fn::Base64: |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          echo "Hello from Auto Scaling" > /var/www/html/index.html

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${AWS::StackName}-instance-sg"
      GroupDescription: Security group for instances
      VpcId: !Ref VPCId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0

Conditions:
  UseSpot: !Equals [!Ref UseSpotInstances, true]

Parameters:
  UseSpotInstances:
    Type: String
    Default: false
    AllowedValues:
      - true
      - false
```

## Launch Templates

### Launch Template with Customization

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with Launch Template

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro

  AmiId:
    Type: AWS::EC2::Image::Id

Resources:
  MyLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: !Sub "${AWS::StackName}-lt"
      LaunchTemplateData:
        ImageId: !Ref AmiId
        InstanceType: !Ref InstanceType
        Monitoring:
          Enabled: true
        NetworkInterfaces:
          - DeviceIndex: 0
            AssociatePublicIpAddress: false
            Groups:
              - !Ref InstanceSecurityGroup
        TagSpecifications:
          - ResourceType: instance
            Tags:
              - Key: Name
                Value: !Sub "${AWS::StackName}-instance"
              - Key: Environment
                Value: !Ref Environment
        UserData:
          Fn::Base64: |
            #!/bin/bash
            yum update -y
            systemctl enable httpd
            systemctl start httpd

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${AWS::StackName}-sg"
      GroupDescription: Security group for instances
      VpcId: !Ref VPCId

  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchTemplate:
        LaunchTemplateId: !Ref MyLaunchTemplate
        Version: !GetAtt MyLaunchTemplate.LatestVersionNumber
```

## Auto Scaling Groups

### ASG with Load Balancer

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling group with Application Load Balancer

Resources:
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref PrivateSubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration
      TargetGroupARNs:
        - !Ref MyTargetGroup
      HealthCheckType: ELB
      HealthCheckGracePeriod: 300
      TerminationPolicies:
        - OldestInstance
        - Default
      InstanceMaintenancePolicy:
        MinHealthyPercentage: 50
        MaxHealthyPercentage: 200
      Tags:
        - Key: Environment
          Value: !Ref Environment
          PropagateAtLaunch: true
        - Key: Name
          Value: !Sub "${AWS::StackName}-instance"
          PropagateAtLaunch: true

  MyTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub "${AWS::StackName}-tg"
      Port: 80
      Protocol: HTTP
      VpcId: !Ref VPCId
      HealthCheckPath: /
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 2
      TargetType: instance
```

### ASG with Launch Template and Mixed Instances

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with Mixed Instances Policy

Resources:
  MyLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: !Sub "${AWS::StackName}-lt"
      LaunchTemplateData:
        ImageId: !Ref AmiId
        InstanceType: t3.micro
        KeyName: !Ref KeyName

  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchTemplate:
        LaunchTemplateId: !Ref MyLaunchTemplate
        Version: !GetAtt MyLaunchTemplate.LatestVersionNumber
      MixedInstancesPolicy:
        InstancesDistribution:
          OnDemandAllocationStrategy: prioritized
          OnDemandBaseCapacity: 2
          OnDemandPercentageAboveBaseCapacity: 50
          SpotAllocationStrategy: capacity-optimized
          SpotInstancePools: 3
          SpotMaxPrice: !Ref MaxSpotPrice
        LaunchTemplate:
          LaunchTemplateId: !Ref MyLaunchTemplate
          Overrides:
            - InstanceType: t3.micro
            - InstanceType: t3.small
            - InstanceType: t3.medium
```

### ASG with Lifecycle Hooks

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with lifecycle hooks

Resources:
  MyLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      LaunchConfigurationName: !Sub "${AWS::StackName}-lc"
      ImageId: !Ref AmiId
      InstanceType: t3.micro

  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration

  # Lifecycle Hook - Instance Launch
  LifecycleHookLaunch:
    Type: AWS::AutoScaling::LifecycleHook
    Properties:
      LifecycleHookName: !Sub "${AWS::StackName}-launch-hook"
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
      HeartbeatTimeout: 900
      NotificationTargetARN: !Ref SnsTopicArn
      RoleARN: !GetAtt LifecycleHookRole.Arn

  # Lifecycle Hook - Instance Termination
  LifecycleHookTermination:
    Type: AWS::AutoScaling::LifecycleHook
    Properties:
      LifecycleHookName: !Sub "${AWS::StackName}-termination-hook"
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING
      HeartbeatTimeout: 3600
      NotificationTargetARN: !Ref SnsTopicArn
      RoleARN: !GetAtt LifecycleHookRole.Arn

  # IAM Role for Lifecycle Hooks
  LifecycleHookRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-lifecycle-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: autoscaling.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-lifecycle-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - sns:Publish
                Resource: !Ref SnsTopicArn

  SnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub "${AWS::StackName}-lifecycle"
```

## Scaling Policies

### Target Tracking Policy

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with Target Tracking scaling policy

Resources:
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration

  TargetTrackingPolicy:
    Type: AWS::AutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-target-tracking"
      PolicyType: TargetTrackingScaling
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      TargetTrackingConfiguration:
        PredefinedMetricSpecification:
          PredefinedMetricType: ASGAverageCPUUtilization
        TargetValue: 70
        DisableScaleIn: false
```

### Step Scaling Policy

```yaml
Resources:
  StepScalingPolicy:
    Type: AWS::AutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-step-scaling"
      PolicyType: StepScaling
      AdjustmentType: PercentChangeInCapacity
      Cooldown: 300
      StepAdjustments:
        - MetricIntervalLowerBound: 0
          MetricIntervalUpperBound: 10000
          ScalingAdjustment: 200
        - MetricIntervalLowerBound: 10000
          MetricIntervalUpperBound: 20000
          ScalingAdjustment: 400
        - MetricIntervalLowerBound: 20000
          ScalingAdjustment: 600
      AutoScalingGroupName: !Ref MyAutoScalingGroup

  # Alarm for Step Scaling
  HighCpuAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub "${AWS::StackName}-high-cpu"
      AlarmDescription: Alarm when CPU utilization is high
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Dimensions:
        - Name: AutoScalingGroupName
          Value: !Ref MyAutoScalingGroup
      Statistic: Average
      Period: 60
      EvaluationPeriods: 3
      Threshold: 70
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Ref StepScalingPolicy
```

### Simple Scaling Policy

```yaml
Resources:
  SimpleScalingPolicy:
    Type: AWS::AutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-simple-scale-up"
      PolicyType: SimpleScaling
      AdjustmentType: ChangeInCapacity
      ScalingAdjustment: 1
      Cooldown: 300
      AutoScalingGroupName: !Ref MyAutoScalingGroup

  ScaleDownPolicy:
    Type: AWS::AutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-simple-scale-down"
      PolicyType: SimpleScaling
      AdjustmentType: ChangeInCapacity
      ScalingAdjustment: -1
      Cooldown: 600
      AutoScalingGroupName: !Ref MyAutoScalingGroup

  HighCpuAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub "${AWS::StackName}-high-cpu"
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Dimensions:
        - Name: AutoScalingGroupName
          Value: !Ref MyAutoScalingGroup
      Statistic: Average
      Period: 120
      EvaluationPeriods: 2
      Threshold: 80
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Ref SimpleScalingPolicy

  LowCpuAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub "${AWS::StackName}-low-cpu"
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Dimensions:
        - Name: AutoScalingGroupName
          Value: !Ref MyAutoScalingGroup
      Statistic: Average
      Period: 300
      EvaluationPeriods: 2
      Threshold: 30
      ComparisonOperator: LessThanThreshold
      AlarmActions:
        - !Ref ScaleDownPolicy
```

### Scheduled Scaling

```yaml
Resources:
  ScheduledScaleUp:
    Type: AWS::AutoScaling::ScheduledAction
    Properties:
      ScheduledActionName: !Sub "${AWS::StackName}-scheduled-scale-up"
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      MinSize: 5
      MaxSize: 15
      DesiredCapacity: 5
      StartTime: "2024-01-01T08:00:00Z"

  ScheduledScaleDown:
    Type: AWS::AutoScaling::ScheduledAction
    Properties:
      ScheduledActionName: !Sub "${AWS::StackName}-scheduled-scale-down"
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      StartTime: "2024-01-01T20:00:00Z"

  # Recurring schedule using cron
  RecurringScaleUp:
    Type: AWS::AutoScaling::ScheduledAction
    Properties:
      ScheduledActionName: !Sub "${AWS::StackName}-morning-scale-up"
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      MinSize: 5
      MaxSize: 15
      DesiredCapacity: 5
      Recurrence: "0 8 * * *"
```

## ECS Auto Scaling

### ECS Service Scaling

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: ECS service with Auto Scaling

Resources:
  # ECS Cluster
  EcsCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub "${AWS::StackName}-cluster"

  # Task Definition
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Sub "${AWS::StackName}-task"
      Cpu: "512"
      Memory: "1024"
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
        - Name: web
          Image: nginx:latest
          PortMappings:
            - ContainerPort: 80
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region

  # ECS Service
  EcsService:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: !Sub "${AWS::StackName}-service"
      Cluster: !Ref EcsCluster
      TaskDefinition: !Ref TaskDefinition
      DesiredCount: 2
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: DISABLED
          SecurityGroups:
            - !Ref ServiceSecurityGroup
          Subnets: !Ref PrivateSubnets
      LoadBalancers:
        - ContainerName: web
          ContainerPort: 80
          TargetGroupArn: !Ref TargetGroup

  # Application Auto Scaling Target
  ScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 10
      MinCapacity: 2
      ResourceId: !Sub "service/${EcsCluster}/${EcsService.Name}"
      RoleARN: !GetAtt EcsServiceScalingRole.Arn
      ScalableDimension: ecs:service:DesiredCount
      ServiceNamespace: ecs

  # Target Tracking Scaling Policy
  EcsTargetTrackingPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-ecs-target-tracking"
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref ScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        PredefinedMetricSpecification:
          PredefinedMetricType: ECSServiceAverageCPUUtilization
        TargetValue: 70
        ScaleInCooldown: 300
        ScaleOutCooldown: 60

  # Log Group
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/ecs/${AWS::StackName}"
      RetentionInDays: 30

  # Security Group
  ServiceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${AWS::StackName}-service-sg"
      GroupDescription: Security group for ECS service
      VpcId: !Ref VPCId

  # Application Load Balancer Target Group
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub "${AWS::StackName}-ecs-tg"
      Port: 80
      Protocol: HTTP
      VpcId: !Ref VPCId
      TargetType: ip

  # IAM Role for ECS Service Scaling with Least Privilege
  EcsServiceScalingRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-ecs-scaling-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: application-autoscaling.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-ecs-scaling-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ecs:DescribeServices
                  - ecs:UpdateService
                Resource: !Sub "arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:service/${EcsCluster}/*"
```

## Lambda Provisioned Concurrency Scaling

### Lambda with Provisioned Concurrency Auto Scaling

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Lambda with Application Auto Scaling for provisioned concurrency

Resources:
  # Lambda Function
  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
      MemorySize: 512
      Timeout: 30
      Role: !GetAtt LambdaExecutionRole.Arn

  # Lambda Version
  LambdaVersion:
    Type: AWS::Lambda::Version
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Description: Version for provisioned concurrency

  # Application Auto Scaling Scalable Target
  LambdaScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 20
      MinCapacity: 5
      ResourceId: !Sub "function:${MyLambdaFunction}:${LambdaVersion.Version}"
      RoleARN: !GetAtt LambdaScalingRole.Arn
      ScalableDimension: lambda:function:ProvisionedConcurrency
      ServiceNamespace: lambda

  # Target Tracking Scaling Policy
  LambdaTargetTrackingPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub "${AWS::StackName}-lambda-target-tracking"
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref LambdaScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 90
        PredefinedMetricSpecification:
          PredefinedMetricType: LambdaProvisionedConcurrencyUtilization
        ScaleInCooldown: 120
        ScaleOutCooldown: 60

  # Lambda Execution Role
  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

  # IAM Role for Lambda Scaling with Least Privilege
  LambdaScalingRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-lambda-scaling-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: application-autoscaling.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-lambda-scaling-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - lambda:PutProvisionedConcurrencyConfig
                  - lambda:GetProvisionedConcurrencyConfig
                Resource: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${MyLambdaFunction}:*"
```

## Conditions and Transform

### Conditions for Environment-Specific Scaling

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Auto Scaling with conditional scaling configuration

Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - staging
      - production

Conditions:
  IsProduction: !Equals [!Ref Environment, production]
  IsStaging: !Equals [!Ref Environment, staging]
  UseSpot: !Or [!Equals [!Ref Environment, dev], !Equals [!Ref Environment, staging]]
  UseAlb: !Not [!Equals [!Ref Environment, dev]]
  EnableDetailedMonitoring: !Not [!Equals [!Ref Environment, dev]]

Resources:
  MyLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      LaunchConfigurationName: !Sub "${AWS::StackName}-lc"
      ImageId: !Ref AmiId
      InstanceType: !If [IsProduction, t3.large, !If [IsStaging, t3.medium, t3.micro]]
      InstanceMonitoring: !If [EnableDetailedMonitoring, Enabled, Basic]

  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: !If [IsProduction, 3, !If [IsStaging, 2, 1]]
      MaxSize: !If [IsProduction, 12, !If [IsStaging, 6, 3]]
      DesiredCapacity: !If [IsProduction, 3, !If [IsStaging, 2, 1]]
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration
      HealthCheckType: !If [UseAlb, ELB, EC2]
      HealthCheckGracePeriod: !If [UseAlb, 300, 300]
```

### Transform for Code Reuse

```yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Description: Using SAM for simplified Auto Scaling

Globals:
  Function:
    Timeout: 30
    Runtime: python3.11
    Tracing: Active
    Environment:
      Variables:
        LOG_LEVEL: INFO

Parameters:
  Environment:
    Type: String
    Default: dev

Resources:
  # Auto Scaling Group using SAM
  WebServerGroup:
    Type: AWS::Serverless::Application
    Properties:
      Location: ./asg-template.yaml
      Parameters:
        Environment: !Ref Environment
```

## CloudFormation Stack Management Best Practices

### Stack Policies

Stack Policies prevent unintentional updates to critical stack resources. Use them to protect Auto Scaling Groups from accidental modifications or deletions.

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Stack with policy to protect Auto Scaling resources

Resources:
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration

  MyLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      LaunchConfigurationName: !Sub "${AWS::StackName}-lc"
      ImageId: !Ref AmiId
      InstanceType: t3.micro

Metadata:
  AWS::CloudFormation::StackPolicy:
    Statement:
      - Effect: Allow
        Resource: "*"
        Action: Update:Modify
      - Effect: Deny
        Resource: "*"
        Action: Update:Delete
        Condition:
          StringEquals:
            ResourceType:
              - AWS::AutoScaling::AutoScalingGroup
              - AWS::AutoScaling::LaunchConfiguration
```

### Termination Protection

Enable termination protection to prevent accidental deletion of Auto Scaling Groups. This is critical for production environments.

```bash
# Enable termination protection on an existing stack
aws cloudformation update-termination-protection \
  --stack-name my-auto-scaling-stack \
  --enable-termination-protection

# Check if termination protection is enabled
aws cloudformation describe-stacks \
  --stack-name my-auto-scaling-stack \
  --query "Stacks[0].EnableTerminationProtection"
```

### Drift Detection

Detect when your Auto Scaling infrastructure has been modified outside of CloudFormation.

```bash
# Detect drift on a stack
aws cloudformation detect-stack-drift \
  --stack-name my-auto-scaling-stack

# Get drift detection status
aws cloudformation describe-stack-drift-detection-status \
  --stack-name my-auto-scaling-stack

# Get drift detection results
aws cloudformation describe-stack-resource-drifts \
  --stack-name my-auto-scaling-stack

# Check specific resource drift
aws cloudformation describe-stack-resource-drifts \
  --stack-name my-auto-scaling-stack \
  --stack-resource-drifts-not-in-sync
```

### Change Sets

Use Change Sets to preview and review changes before applying them to your Auto Scaling infrastructure.

```bash
# Create a change set
aws cloudformation create-change-set \
  --stack-name my-auto-scaling-stack \
  --change-set-name my-changeset \
  --template-body file://template.yaml \
  --parameters ParameterKey=Environment,ParameterValue=production

# List change sets
aws cloudformation list-change-sets \
  --stack-name my-auto-scaling-stack

# Describe change set
aws cloudformation describe-change-set \
  --stack-name my-auto-scaling-stack \
  --change-set-name my-changeset

# Execute change set
aws cloudformation execute-change-set \
  --stack-name my-auto-scaling-stack \
  --change-set-name my-changeset
```

```yaml
# Automated change set creation in CI/CD pipeline
Resources:
  ChangeSetRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: ChangeSetPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - autoscaling:Describe*
                  - cloudwatch:Describe*
                  - ec2:Describe*
                Resource: "*"
              - Effect: Allow
                Action:
                  - autoscaling:UpdateAutoScalingGroup
                  - autoscaling:CreateOrUpdateTags
                  - cloudwatch:PutMetricAlarm
                  - cloudwatch:DeleteAlarms
                Resource:
                  - !Sub "arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/*"
                  - !Sub "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
```

## Best Practices

### High Availability

- Distribute instances across multiple AZs
- Use ALB with health checks for automatic routing
- Implement lifecycle hooks for graceful shutdown
- Configure appropriate termination policies
- Use mixed instances policies for diversity

### Cost Optimization

- Use Spot Instances for fault-tolerant workloads
- Implement right-sizing of instances
- Configure aggressive scale-in policies
- Use scheduled scaling for predictable patterns
- Monitor and optimize regularly

### Monitoring

- Create CloudWatch Alarms for key metrics
- Implement scaling policies based on metrics
- Use lifecycle hooks for logging and analytics
- Configure SNS notifications for scaling events
- Implement detailed monitoring for troubleshooting

### Security

- Use IAM roles with minimum permissions
- Encrypt EBS volumes with KMS
- Configure restrictive security groups
- Use VPC with appropriate subnets
- Implement parameter store for sensitive configuration
- Avoid using broad managed policies like `CloudWatchFullAccess`
- Use specific permissions instead of broad managed policies

#### Least Privilege IAM Examples

```yaml
# Instead of CloudWatchFullAccess, use specific permissions
ScalingAlarmRole:
  Type: AWS::IAM::Role
  Properties:
    RoleName: !Sub "${AWS::StackName}-scaling-alarm-role"
    AssumeRolePolicyDocument:
      Version: "2012-10-17"
      Statement:
        - Effect: Allow
          Principal:
            Service: autoscaling.amazonaws.com
          Action: sts:AssumeRole
    Policies:
      - PolicyName: !Sub "${AWS::StackName}-cloudwatch-specific-policy"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - cloudwatch:PutMetricAlarm
                - cloudwatch:DescribeAlarms
                - cloudwatch:DeleteAlarms
                - cloudwatch:EnableAlarmActions
                - cloudwatch:DisableAlarmActions
              Resource: !Sub "arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
```

## Examples

The following examples demonstrate common Auto Scaling patterns:

### Example 1: EC2 Auto Scaling Group with ALB

Complete ASG with Application Load Balancer, health checks, and target tracking scaling:

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Production EC2 Auto Scaling with ALB

Resources:
  MyAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Sub "${AWS::StackName}-asg"
      MinSize: 2
      MaxSize: 10
      DesiredCapacity: 2
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchConfigurationName: !Ref MyLaunchConfiguration
      TargetGroupARNs:
        - !Ref MyTargetGroup
      HealthCheckType: ELB
      HealthCheckGracePeriod: 300
```

### Example 2: Target Tracking Scaling Policy

```yaml
TargetTrackingPolicy:
  Type: AWS::AutoScaling::ScalingPolicy
  Properties:
    PolicyName: !Sub "${AWS::StackName}-target-tracking"
    PolicyType: TargetTrackingScaling
    AutoScalingGroupName: !Ref MyAutoScalingGroup
    TargetTrackingConfiguration:
      PredefinedMetricSpecification:
        PredefinedMetricType: ASGAverageCPUUtilization
      TargetValue: 70
```

### Example 3: Lifecycle Hooks

```yaml
LifecycleHookLaunch:
  Type: AWS::AutoScaling::LifecycleHook
  Properties:
    LifecycleHookName: !Sub "${AWS::StackName}-launch-hook"
    AutoScalingGroupName: !Ref MyAutoScalingGroup
    LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
    HeartbeatTimeout: 900
    NotificationTargetARN: !Ref SnsTopicArn
    RoleARN: !GetAtt LifecycleHookRole.Arn
```

For complete production-ready examples, see [EXAMPLES.md](references/examples.md).

## Related Resources

- [Auto Scaling Documentation](https://docs.aws.amazon.com/autoscaling/)
- [AWS CloudFormation User Guide](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/)
- [Auto Scaling Best Practices](https://docs.aws.amazon.com/autoscaling/plans/userguide/auto-scaling-best-practices.html)
- [Application Auto Scaling](https://docs.aws.amazon.com/autoscaling/application/userguide/what-is-application-auto-scaling.html)

## Additional Files

## Constraints and Warnings

### Resource Limits

- **Auto Scaling Group Limits**: Maximum 100 Auto Scaling Groups per region per AWS account
- **Launch Configuration/Launch Template Limits**: Maximum number of launch configurations and templates per region
- **Scaling Policy Limits**: Maximum 500 step adjustments in a step scaling policy
- **Lifecycle Hooks**: Maximum number of lifecycle hooks per Auto Scaling Group varies by instance type

### Scaling Constraints

- **Cooldown Periods**: Scaling cooldowns prevent rapid scale-in/scale-out oscillations but can delay response to demand changes
- **Health Check Grace Period**: Too short grace period may cause termination of instances still bootstrapping
- **Minimum/Maximum Capacity**: Exceeding these limits prevents scaling operations
- **Instance Termination**: Scale-in terminates instances without graceful shutdown by default

### Operational Constraints

- **Mixed Instances Policy**: Not all instance types support on-demand/Spot allocation
- **Predictive Scaling**: Requires at least 24 hours of metric data before predictions are accurate
- **Instance Refresh**: Replacing all instances simultaneously can cause service disruption
- **Scaling Policies**: Multiple scaling policies targeting the same metric can cause unpredictable behavior

### Cost Considerations

- **Spot Instances**: Can be terminated with 2-minute notice; not suitable for stateful workloads
- **Over-provisioning**: Setting minimum capacity too high leads to unnecessary costs
- **Scaling Frequency**: Frequent scaling activities can accumulate costs from instance provisioning

### Security Constraints

- **IAM Roles**: Auto Scaling requires IAM roles with appropriate permissions for lifecycle hooks
- **Service-Linked Roles**: Auto Scaling requires creation of service-linked role for certain operations
- **Launch Template Permissions**: Launch templates referencing encrypted AMIs require KMS permissions

## Additional Files

For complete details on resources and their properties, consult:
- [REFERENCE.md](references/reference.md) - Detailed reference guide for all CloudFormation resources
- [EXAMPLES.md](references/examples.md) - Complete production-ready examples

Overview

This skill provides production-ready AWS CloudFormation patterns for Auto Scaling across EC2, ECS, and Lambda. It bundles templates and guidance for launch configurations, launch templates, Auto Scaling Groups, scaling policies, lifecycle hooks, and predictive scaling. Use it to structure templates with Parameters, Mappings, Conditions, Outputs and to implement cross-stack references for modular infrastructure.

How this skill works

The skill supplies CloudFormation patterns and concrete template snippets that define launch resources (LaunchConfiguration/LaunchTemplate), Auto Scaling Groups, scaling policies (target tracking, step, simple), and lifecycle hooks. It shows how to use AWS-specific parameter types, SSM references, CloudWatch alarms, and export/import outputs so stacks can share ASG names, ARNs, and scaling policy ARNs. Examples include templates for ALB-backed ASGs, mixed instance policies, and nested stacks for modular deployment.

When to use it

  • When creating Auto Scaling Groups for EC2 instances or ECS services
  • When converting ad-hoc infrastructure into reusable CloudFormation templates
  • When implementing predictable scaling with target-tracking or predictive policies
  • When adding lifecycle hooks for instance initialization or custom termination work
  • When using mixed instance policies or spot capacity to optimize cost
  • When you need cross-stack exports/imports or nested stacks for modularity

Best practices

  • Use AWS-specific parameter types (e.g., AWS::EC2::Image::Id, Subnet::Id) for validation
  • Constrain numeric parameters (MinSize/MaxSize/DesiredCapacity) to safe ranges
  • Prefer Launch Templates for advanced settings and consistent AMI/instance type management
  • Leverage SSM Parameter values for latest AMIs and centralized configuration
  • Export minimal, stable outputs (ASG name/ARN, LaunchTemplateId) for cross-stack references
  • Add CloudWatch alarms and cooldowns to avoid flapping and control costs

Example use cases

  • Template an ALB-backed EC2 Auto Scaling Group with health checks and graceful termination
  • Create a Launch Template and ASG with mixed instance policy to combine on-demand and spot
  • Provision ECS service scaling with target-tracking policies based on service CPU or memory
  • Scale Lambda provisioned concurrency with scheduled or predictive scaling policies
  • Split networking, compute, and scaling policies into nested stacks for CI/CD deployments

FAQ

Should I use Launch Configurations or Launch Templates?

Prefer Launch Templates for new deployments because they support more features (instance metadata options, multiple versions, mixed instances) and are the modern AWS recommendation.

How do I safely reference an ASG from another stack?

Export the ASG name or ARN in the infrastructure stack Outputs and import it with !ImportValue in the application stack, keeping exported names stable.