Match policy to demand pattern
Target tracking keeps a metric near a target, such as average CPU at 40% or ALB request count per target. Step scaling changes capacity based on how far a threshold is breached. Scheduled actions fit known demand; predictive scaling forecasts repeating daily or weekly patterns from history.
flowchart LR M["CloudWatch metric<br/>CPU 75%"] --> P["Target tracking<br/>keep CPU at 50%"] P --> O["Scale out<br/>desired 2 to 4"] O --> W["Instance warmup<br/>300 s"] W --> M P --> I["Scale in<br/>slowly, when calm"] I --> TP["Termination policy<br/>balance AZs first"] %% step M: Instances report metrics such as average CPU to CloudWatch. %% step P: Target tracking creates and manages the alarms for you and computes how many instances are needed. %% step O: When the metric is above target, desired capacity rises. %% step W: New instances are ignored in the average until warmed up, so the group does not overshoot. %% step I: When load drops, the group removes instances more cautiously than it adds them. %% step TP: It keeps AZs balanced and then follows the termination policy to choose which instance goes.
Policy types
| Policy | You define | Best for |
|---|---|---|
| Target tracking | A metric and target value | Most workloads; simplest |
| Step scaling | Alarm thresholds and step sizes (e.g. +1 above 60%, +3 above 80%) | Fine control, sharp spikes |
| Simple scaling | One adjustment per alarm, then a cooldown | Legacy; prefer the others |
| Scheduled | Time and new min/desired/max | Known events: business hours, launches |
| Predictive | Metric to forecast | Regular daily or weekly cycles |
Policies can be combined: a scheduled action raises the minimum before office hours while target tracking handles the rest. When several policies want different capacities, the ASG picks the one giving the largest capacity, which favours availability.
Choosing a metric
Good scaling metrics rise and fall with load: ASGAverageCPUUtilization, ALBRequestCountPerTarget, network in/out, or a custom metric such as SQS queue backlog per instance for workers. Memory is a poor default because many apps never release it.
Warmup and cooldown
Instance warmup prevents not-yet-ready instance metrics from distorting decisions. Cooldown mainly relates to simple scaling; too short can oscillate (flapping), while too long reacts slowly. Set the default instance warmup on the group to roughly how long an instance takes to serve traffic.
Scale-in safety
During scale-in, the ASG first balances AZs and then applies its termination policy (default: oldest launch template or configuration, then closest to the next billing hour). Instance scale-in protection can preserve selected instances, for example one running a long job; lifecycle hooks allow draining or processing before termination. Target tracking can be set to scale out only (DisableScaleIn) if you scale in another way.
| Command | Purpose |
|---|---|
aws autoscaling put-scaling-policy --auto-scaling-group-name web-asg --policy-name cpu50 --policy-type TargetTrackingScaling --target-tracking-configuration file://cpu50.json |
Create target tracking |
aws autoscaling put-scheduled-update-group-action --auto-scaling-group-name web-asg --scheduled-action-name office --recurrence "0 1 * * 1-5" --min-size 4 |
Add a scheduled action (cron in UTC) |
aws autoscaling describe-policies --auto-scaling-group-name web-asg |
View policies |
aws autoscaling set-instance-protection --instance-ids i-0a1b2c3d --auto-scaling-group-name web-asg --protected-from-scale-in |
Protect one instance |
Traps: scaling on memory by default; a warmup shorter than boot time causing over-scaling; forgetting that scheduled cron times are UTC by default.