Auto Scaling Groups & Policies
Key concepts
Launch templates
Target tracking scaling
Step scaling policies
Scheduled scaling
Predictive scaling
Overview
Amazon EC2 Auto Scaling helps you maintain application availability by automatically adding or removing EC2 instances based on demand. It ensures you have the right number of instances running to handle the load, optimizing both performance and cost.
For the SAA-C03 exam, Auto Scaling is heavily tested across multiple domains. You need to understand the different scaling policies, when to use each, how health checks work, and advanced features like warm pools and lifecycle hooks.
Core Principle
Auto Scaling provides elasticity - automatically scaling capacity up or down based on demand. It ensures high availability by replacing unhealthy instances and distributing across AZs. You only pay for the instances running, not for Auto Scaling itself.
Expect questions comparing scaling policies (target tracking vs step vs scheduled), understanding cooldown periods, and knowing when to use launch templates vs launch configurations (hint: always use launch templates now).
Architecture Diagram
The following diagram illustrates an Auto Scaling Group with Elastic Load Balancing:

Key Concepts
Auto Scaling Group Components
Auto Scaling Group (ASG)
An Auto Scaling Group contains a collection of EC2 instances that share similar characteristics and are treated as a logical grouping for scaling and management.
Core Settings:
- Minimum capacity: Minimum number of instances (never goes below)
- Maximum capacity: Maximum number of instances (never exceeds)
- Desired capacity: Target number of instances ASG maintains
Example Configuration:
- Min: 2, Max: 10, Desired: 4
- ASG maintains 4 instances
- Can scale out to 10 during peak load
- Never drops below 2 instances
Launch Templates vs Launch Configurations
Launch Templates (Recommended)
Launch Templates define the instance configuration for ASG:
- AMI ID
- Instance type
- Key pair
- Security groups
- Block device mappings
- IAM instance profile
- User data scripts
Advantages over Launch Configurations:
- Support for multiple instance types (mixed instances)
- Versioning support
- Can specify Spot and On-Demand mix
- Required for new instance types (post-2023)
Launch Configurations Deprecated
Launch Configurations are deprecated:
- No new instance types supported after Jan 1, 2023
- New accounts (after Oct 1, 2024) cannot create them
- Always use Launch Templates for new ASGs
- Migrate existing Launch Configurations to Launch Templates
How It Works
Scaling Policies

Scaling Policy Types
| Policy Type | How It Works | Best For | Cooldown |
|---|---|---|---|
| Target Tracking | Maintains metric at target value (like thermostat) | Most use cases, simplest to configure | Built-in (no manual cooldown) |
| Step Scaling | Multiple steps based on alarm breach size | Fine-grained control, variable scaling | Configurable |
| Simple Scaling | Single adjustment on alarm | Legacy, simple scenarios | Required (default 300s) |
| Scheduled | Scale at specific times | Predictable load patterns | N/A |
| Predictive | ML-based forecast, proactive scaling | Recurring patterns, traffic spikes | N/A |
Target Tracking Scaling
Target Tracking Scaling
Target tracking works like a thermostat - you set a target value, and ASG adjusts to maintain it.
Predefined Metrics:
ASGAverageCPUUtilization- Average CPU across instancesASGAverageNetworkIn- Average bytes receivedASGAverageNetworkOut- Average bytes sentALBRequestCountPerTarget- Requests per target from ALB
Custom Metrics:
- Any CloudWatch metric (e.g., SQS queue depth per instance)
Behavior:
- Scales out quickly when metric exceeds target
- Scales in gradually to avoid flapping
- Creates and manages CloudWatch alarms automatically
{
"TargetTrackingConfiguration": {
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
},
"TargetValue": 50.0,
"DisableScaleIn": false
}
}
// Maintains ~50% average CPU utilization
// Adds instances when CPU > 50%
// Removes instances when CPU < 50%Step Scaling
Step Scaling
Step scaling allows different scaling actions based on the size of the alarm breach.
Example Configuration:
CPU 60-70%: Add 1 instance
CPU 70-80%: Add 2 instances
CPU > 80%: Add 3 instances
Advantages:
- More control than simple scaling
- Can react proportionally to breach size
- Supports both scale-out and scale-in steps
Step Adjustments:
ChangeInCapacity: Add/remove specific numberExactCapacity: Set to specific countPercentChangeInCapacity: Increase/decrease by percentage
Scheduled Scaling
Scheduled Scaling
Scheduled scaling performs scaling actions at specific times.
Use Cases:
- Scale up before business hours
- Scale down on weekends
- Prepare for known events (sales, releases)
Schedule Options:
- One-time schedule (specific date/time)
- Recurring schedule (cron expression)
Example:
Scale to 10 instances at 8 AM weekdays
Scale to 2 instances at 8 PM weekdays
Scale to 2 instances all day weekends
Predictive Scaling
Predictive Scaling
Predictive scaling uses machine learning to forecast load and proactively scale.
How It Works:
- Analyzes up to 14 days of historical data
- Identifies daily and weekly patterns
- Creates forecast for next 48 hours
- Proactively launches instances before demand increases
Requirements:
- At least 24 hours of historical data
- Works best with recurring patterns
- Can combine with dynamic scaling policies
Modes:
- Forecast only: View predictions without scaling
- Forecast and scale: Automatically scale based on predictions
Health Checks
Health Check Types
ASG monitors instance health and replaces unhealthy instances:
EC2 Health Check (Default):
- Checks EC2 status checks (system and instance)
- Instance marked unhealthy if status check fails
- Replaced automatically
ELB Health Check (Optional):
- Uses load balancer health checks
- Instance unhealthy if ELB reports unhealthy
- Recommended when using ELB
Custom Health Check:
- Application sends health status via API
- Use
set-instance-healthcommand - For application-level health monitoring
Health Check Comparison
| Check Type | What It Monitors | When to Use |
|---|---|---|
| EC2 Status | Hardware/hypervisor issues | Always enabled (default) |
| ELB Health | Application responding to requests | When using ALB/NLB/CLB |
| Custom | Application-specific health | Complex health requirements |
Health Check Grace Period
Health Check Grace Period
The grace period is the time ASG waits before checking health on new instances.
- Default: 300 seconds (console) or 0 seconds (CLI/SDK)
- Purpose: Allow time for instance initialization
- Set based on how long your application takes to start
- During grace period, unhealthy status is ignored
Best Practice: Set grace period slightly longer than your application startup time.
Cooldown Period
Cooldown Period
The cooldown period prevents rapid-fire scaling actions.
How It Works:
- After a scaling activity, ASG waits before next action
- Allows previous instances to start handling traffic
- Prevents over-scaling or thrashing
Default: 300 seconds
Types:
- Default cooldown: Applies to all scaling activities
- Scale-out cooldown: Specific to scale-out actions
- Scale-in cooldown: Specific to scale-in actions
Note: Target tracking policies have built-in warmup and don't use cooldowns the same way.
Warm Pools

Warm Pools
Warm pools reduce scale-out latency by maintaining pre-initialized instances.
How It Works:
- Instances launched and initialized (run user data scripts)
- Instances stopped or hibernated (not running, no compute cost)
- On scale-out: Instances started instead of launched fresh
- Much faster than launching cold instances
States:
- Stopped: No compute cost, storage cost only
- Hibernated: Preserves memory state, faster start
- Running: Full cost (rarely used)
Use Cases:
- Applications with long initialization (5+ minutes)
- Pre-loading large datasets or caches
- Complex bootstrap processes
Lifecycle Hooks
Lifecycle Hooks
Lifecycle hooks pause instances during launch or termination to perform custom actions.
Launch Hook (scale-out):
- Instance pauses in
Pending:Waitstate - Run custom initialization scripts
- Install software, configure settings
- Complete hook to continue to
InService
Termination Hook (scale-in):
- Instance pauses in
Terminating:Waitstate - Download logs, deregister from services
- Backup data before termination
- Complete hook to continue termination
Timeout: Default 1 hour (configurable)
Integration Options:
- EventBridge → Lambda
- SNS notifications
- SQS messages
SCALE-OUT:
Pending → Pending:Wait → [Custom Actions] → Pending:Proceed → InService
SCALE-IN:
InService → Terminating → Terminating:Wait → [Custom Actions] → Terminating:Proceed → Terminated
Custom Actions Examples:
- Download and install software packages
- Register with configuration management (Chef, Puppet)
- Download logs before termination
- Deregister from external servicesMixed Instances Policy
Mixed Instances Policy
Mixed instances policy allows combining instance types and purchase options.
Instance Types:
- Specify multiple instance types (e.g., m5.large, m5.xlarge, m4.large)
- ASG selects based on availability and priorities
- Improves availability (not dependent on single type)
Purchase Options:
- On-Demand instances (reliable, higher cost)
- Spot instances (up to 90% savings, can be interrupted)
- Configure percentage split (e.g., 70% Spot, 30% On-Demand)
Allocation Strategies:
- lowest-price: Launch cheapest Spot pools
- capacity-optimized: Launch from pools with most capacity
- price-capacity-optimized: Balance price and capacity (recommended)
Decision Guide
Use Cases
Use Case 1: Web Application with Variable Traffic
Scenario: E-commerce site with traffic varying by time of day and sales events.
Solution:
- Target tracking policy (50% CPU utilization)
- Scheduled scaling (increase min capacity before sales)
- Predictive scaling for daily patterns
- ELB health checks enabled
- Grace period: 300 seconds
Use Case 2: Batch Processing with SQS
Scenario: Processing queue that varies significantly in depth.
Solution:
- Custom metric:
ApproximateNumberOfMessages / DesiredCapacity - Target tracking on custom metric (target: 100 messages per instance)
- Scale to zero when queue is empty
- Step scaling for burst scenarios
Use Case 3: Application with Long Startup Time
Scenario: Java application taking 10 minutes to initialize.
Solution:
- Warm pools with stopped instances
- Lifecycle hooks for initialization verification
- Grace period: 720 seconds (12 minutes)
- Predictive scaling to launch before demand
Best Practices
Auto Scaling Best Practices
- Use Launch Templates - Not Launch Configurations (deprecated)
- Enable ELB health checks - When using load balancers
- Set appropriate grace period - Longer than app startup time
- Use target tracking as baseline - Simplest and most effective
- Distribute across AZs - At least 2 AZs for high availability
- Right-size instances first - Scale right-sized instances, not oversized
- Monitor scaling activities - CloudWatch alarms for failures
- Use warm pools - For applications with long initialization
- Consider mixed instances - Spot for cost savings, multiple types for availability
Common Exam Scenarios
Exam Scenarios and Solutions
| Scenario | Solution | Why |
|---|---|---|
| Maintain 50% average CPU across instances | Target tracking with ASGAverageCPUUtilization | Target tracking automatically adjusts to maintain metric |
| Scale up before known traffic spike | Scheduled scaling action | Proactively increase capacity before demand |
| Variable scaling based on alarm breach size | Step scaling policy | Different step adjustments for different breach levels |
| Reduce cold start latency for scale-out | Warm pools | Pre-initialized instances ready to start quickly |
| Run custom script before termination | Termination lifecycle hook | Pauses termination to allow custom actions |
| Mix Spot and On-Demand instances | Mixed instances policy with launch template | Launch configurations dont support mixed instances |
| Instance healthy per EC2 but app not responding | Enable ELB health checks | ELB checks application health, not just EC2 status |
| Scale based on SQS queue depth | Custom metric + target tracking | Messages per instance metric with target tracking |
Common Pitfalls
Pitfall 1: Not Enabling ELB Health Checks
Mistake: Using only EC2 health checks when instances are behind a load balancer.
Why it fails:
- EC2 checks only verify the instance is running
- Application may be unresponsive but instance "healthy"
- ELB removes instance but ASG doesn't replace it
Correct Approach:
- Always enable ELB health checks when using ALB/NLB
- ASG will replace instances that fail ELB health checks
- Set appropriate health check grace period
Pitfall 2: Grace Period Too Short
Mistake: Setting health check grace period shorter than application startup time.
Why it fails:
- Instance marked unhealthy before it finishes starting
- ASG terminates and replaces it
- Replacement also fails → infinite replacement loop
Correct Approach:
- Measure actual application startup time
- Set grace period slightly longer (add 20% buffer)
- Use lifecycle hooks for complex initialization
Pitfall 3: Using Launch Configurations for New Projects
Mistake: Creating new ASGs with Launch Configurations.
Why it fails:
- No support for new instance types (post-2023)
- Cannot use mixed instances policy
- No versioning support
- Deprecated and being phased out
Correct Approach:
- Always use Launch Templates
- Migrate existing Launch Configurations
- Use template versioning for changes
Pitfall 4: Cooldown Too Short for Step Scaling
Mistake: Setting very short cooldown periods with step scaling.
Why it fails:
- Multiple scaling activities triggered rapidly
- Over-provisioning occurs before previous instances are ready
- Costs increase unnecessarily
Correct Approach:
- Use target tracking (has built-in warmup)
- If using step scaling, set cooldown based on instance warmup time
- Consider instance warmup setting for accurate metrics
Test Your Knowledge
Which scaling policy type is recommended for most use cases and works like a thermostat?
What happens when an instance fails an ELB health check but ELB health checks are NOT enabled in the ASG?
A company needs to combine Spot and On-Demand instances in their Auto Scaling group. What must they use?
What is the purpose of a warm pool in Auto Scaling?
Related Services
AWS Systems Manager
Run Command can be used with lifecycle hooks for instance configuration
Quick Reference
Scaling Policy Comparison
When to Use Each Policy
| Policy | Use When | Avoid When |
|---|---|---|
| Target Tracking | Want simplest configuration, maintain specific metric | Need complex multi-step responses |
| Step Scaling | Need proportional response to breach size | Simple scaling needs are sufficient |
| Simple Scaling | Very basic scaling needs (legacy) | Almost always - use target tracking instead |
| Scheduled | Load patterns are predictable and time-based | Load is unpredictable |
| Predictive | Historical patterns exist, want proactive scaling | Workload has no recurring patterns |
Key Limits and Defaults
Auto Scaling Limits and Defaults
| Setting | Default | Maximum |
|---|---|---|
| ASGs per region | 200 | Adjustable |
| Launch templates per region | 5,000 | Adjustable |
| Instances per ASG | Varies | Desired capacity limit |
| Scaling policies per ASG | 50 | Hard limit |
| Scheduled actions per ASG | 125 | Hard limit |
| Lifecycle hooks per ASG | 50 | Hard limit |
| Health check grace period | 300 seconds (console) | Unlimited |
| Default cooldown | 300 seconds | Unlimited |
Common Metrics for Scaling
CPU-Based:
Metric: ASGAverageCPUUtilization
Target: 40-70% (depends on workload)
Network-Based:
Metric: ASGAverageNetworkIn or ASGAverageNetworkOut
Target: Based on instance network capacity
Request-Based (with ALB):
Metric: ALBRequestCountPerTarget
Target: Based on application capacity per instance
Queue-Based (SQS):
Metric: Custom (ApproximateNumberOfMessages / GroupDesiredCapacity)
Target: Messages each instance should process