AWS Auto Scaling Groups Explained for Beginners

An Auto Scaling Group (ASG) is an AWS service that manages a fleet of EC2 instances for you. You define minimum, maximum, and desired instance counts; AWS handles the rest: launching new instances when demand rises, terminating them when demand drops, and replacing any instance that fails health checks. An ASG manages EC2 capacity; it does not receive traffic itself. For web applications, you typically pair it with an Application Load Balancer that distributes traffic across the instances the ASG maintains.

The practical outcome: your application stays available during failures (self-healing), scales to meet demand without manual intervention (elasticity), and only runs as many instances as it actually needs (cost efficiency). For any production workload where uptime and variable load matter, ASGs are one of the most valuable tools AWS offers.

Simple explanation

That is the core idea. The rest of this page explains the mechanisms behind it and how to use them well.

Why Auto Scaling Groups matter

Without ASGs, every EC2 deployment forces a choice: over-provision for peak load (pay for idle capacity most of the time) or under-provision for average load (save money but fall over during traffic spikes). ASGs remove that trade-off by matching capacity to actual demand.

ASGs also solve the single-point-of-failure problem. One EC2 instance fails and your service goes down. An ASG with a minimum of two instances spread across two Availability Zones means that even a full AZ outage does not take the service offline.

The practical benefits:

  • Resilience: Failed instances are replaced automatically. No on-call alert needed to restart a crashed server.
  • Elasticity: Capacity tracks demand, so traffic spikes do not cause outages and quiet periods do not waste money.
  • Lower operational overhead: You define the rules once; AWS enforces them continuously.
  • Cost efficiency: You only run what you need, especially when combined with Spot Instances for non-critical capacity.

How Auto Scaling Groups work

Here is the full flow for a typical stateless web application running across two Availability Zones:

  1. A launch template defines what to launch. The launch template stores the AMI, instance type, security groups, IAM role, and any user data script that runs on first boot. When the ASG needs a new instance, it reads the launch template and creates an exact copy.
  2. The ASG spans subnets across AZs and maintains desired capacity. You provide subnets in two or more AZs. AWS distributes instances evenly: desired=4 across 2 AZs gives 2 instances per AZ. See Regions and Availability Zones for how this reduces blast radius.
  3. A load balancer provides a stable traffic entry point for web apps. You register the ASG with an Application Load Balancer target group. The ALB routes traffic only to healthy instances and automatically includes new instances as they pass health checks.
  4. Health checks identify bad instances. The ASG monitors each instance. Any instance that fails health checks is marked unhealthy, terminated, and replaced automatically.
  5. Scaling policies adjust desired capacity. CloudWatch metrics (CPU, request count, custom metrics) trigger scaling policies that increase or decrease desired capacity. AWS then launches or terminates instances to match the new target.
  6. Instance refresh rolls out launch template changes safely. When you update the launch template, existing instances are not affected until you start an instance refresh. AWS replaces them in batches, keeping the fleet healthy throughout.

A concrete example: you run a Django application behind an ALB. The ASG has min=2, max=8, desired=2. At noon, CPU climbs to 75%. A target tracking policy fires and increases desired to 4. AWS launches two new instances using the launch template, waits for them to pass the ALB health check, and the ALB begins routing traffic to them. At 3am, CPU drops. The policy scales desired back to 2 and AWS terminates the extra instances cleanly.

Core settings: min, max, and desired capacity

Every ASG has three capacity settings:

  • Minimum capacity: The floor. The ASG will never have fewer instances than this, regardless of scaling-in events. Set to at least 2 in production if you need high availability.
  • Maximum capacity: The ceiling. No scaling policy can exceed this. Protects against runaway scaling and unexpected costs. Set it thoughtfully: too low and your application cannot scale; too high and a bug in a scaling policy could launch hundreds of instances.
  • Desired capacity: The current target. AWS tries to maintain exactly this many healthy instances at all times. Scaling policies work by changing desired capacity; AWS then adds or removes instances to match it.

Example: min=2, max=10, desired=4. AWS runs four instances. A scaling policy fires and sets desired=7. AWS launches three more. Later, desired drops to 2. AWS terminates two. The fleet never goes below 2 or above 10.

Required building blocks

Before creating an ASG, you need each of these in place:

  • Launch template: Defines the AMI, instance type, key pair, security groups, IAM instance profile, and startup script. The ASG reads this every time it needs to launch a new instance. Use versioned launch templates: update the template, then trigger an instance refresh rather than modifying the ASG directly.
  • Subnets and Availability Zones: List one or more subnets, ideally spread across at least two AZs. AWS balances instances across them automatically. A single-subnet ASG has no AZ-level redundancy.
  • Load balancer and target group (for web workloads): The Application Load Balancer acts as the stable traffic entry point. The ASG registers and deregisters instances with the target group as they launch and terminate. Not every ASG needs a load balancer. Batch jobs and background workers typically do not.
  • Health checks: Either EC2 health checks (default) or ELB health checks if you are using a load balancer. Covered in detail below.
  • Scaling policies: CloudWatch alarms or metric targets that tell the ASG when to grow or shrink. Without scaling policies, the ASG maintains a fixed desired capacity and only replaces unhealthy instances.

Create an ASG with a launch template using the AWS CLI:

aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name production-web-asg \
  --launch-template "LaunchTemplateName=web-server-template,Version=\$Latest" \
  --min-size 2 \
  --max-size 10 \
  --desired-capacity 2 \
  --vpc-zone-identifier "subnet-0abc,subnet-0def" \
  --health-check-type ELB \
  --health-check-grace-period 120 \
  --tags "Key=Environment,Value=production,PropagateAtLaunch=true"

The vpc-zone-identifier lists subnets, one per AZ. AWS distributes instances across these AZs automatically. The —health-check-type ELB flag enables application-level health checks through the attached load balancer.

Health checks

The ASG monitors every instance and replaces any that become unhealthy. There are two health check types:

EC2 health checks (default)

AWS checks the EC2 instance and system status. If an instance has a hardware failure, kernel panic, or networking issue, the ASG marks it unhealthy and replaces it. This catches infrastructure-level failures but cannot tell whether your application code is actually working correctly.

ELB health checks

When the ASG is attached to a load balancer, you can switch to ELB health checks. The load balancer periodically sends an HTTP request to a health endpoint on each instance. If the instance fails to respond (due to a timeout, connection refused, or HTTP 5xx error), the load balancer marks it unhealthy, stops routing traffic to it, and the ASG terminates and replaces it.

ELB health checks catch application-level failures that EC2 checks miss: your process has crashed, your app is returning errors, or a dependency has wedged the service. For any web workload using a load balancer, switch to ELB health checks.

A load balancer is not always required. A fleet of background workers pulling from a queue does not need one, and EC2 health checks are perfectly adequate for that pattern. If you do use a load balancer, ELB health checks are the better choice. See Load Balancer Backend Unhealthy for help diagnosing health check failures.

Grace period trap

The —health-check-grace-period is the number of seconds the ASG waits after launching a new instance before starting health checks. If health checks begin before the app is ready, the new instance gets marked unhealthy and terminated immediately, then a replacement launches and the same thing happens again. Set the grace period to a value comfortably longer than your worst-case startup time.

Scaling policies

Scaling policies define when and how the ASG’s desired capacity changes. CloudWatch provides the metrics that drive them. See Metrics in AWS for how to choose which metrics matter for your workload.

The main policy types:

  • Target tracking: You specify a metric and a target value (for example, keep average CPU at 60%). AWS adjusts desired capacity automatically to hit that target, scaling out when the metric rises and scaling in when it falls. This is the simplest approach and works well for most workloads. Start here.
  • Step scaling: You define thresholds and capacity adjustments. If CPU exceeds 70%, add 1 instance. If CPU exceeds 90%, add 3. More flexible than target tracking but requires more tuning. Avoid overly aggressive thresholds: noisy metrics can cause rapid scaling events that hurt stability.
  • Scheduled scaling: Set desired capacity on a fixed schedule. Useful when you know your traffic pattern: always scale to 10 at 9am on weekdays and back to 2 at 8pm. Pair with target tracking so the ASG can still respond to unexpected demand outside the schedule.
Where to start

If you are new to ASGs, configure target tracking on CPU utilisation or request count first. It requires the least tuning and handles the majority of traffic patterns well. Add step scaling or scheduled scaling only once you understand how your application responds to load.

When choosing scaling metrics, prefer metrics that reflect actual user experience (request latency, queue depth, active connections) over proxy metrics like CPU. CPU can look fine while your application is saturated on memory or database connections. The Autoscaling Policies guide covers each type in detail with examples.

Spot and mixed instance options

When using a launch template, ASGs support mixed instance policies that combine On-Demand and Spot capacity in any ratio. For example: two On-Demand instances as a guaranteed baseline, with all scale-out using Spot capacity. If AWS reclaims a Spot Instance (with a two-minute warning), the ASG launches a replacement automatically.

Cost saving potential

A mixed fleet running 2 On-Demand instances as a baseline and scaling out with Spot can reduce EC2 costs by 60–80% compared to an all-On-Demand fleet of the same peak size. The saving is highest for large fleets with big peak-to-trough ratios. See EC2 Spot Instances Explained for how interruption handling works in practice.

Keep On-Demand instances for your minimum guaranteed capacity. Use Spot for the elastic portion only: instances that can be interrupted and replaced without affecting the service.

Warm-up, grace periods, and rollout behaviour

New instances need time to become ready. Several ASG settings control how this is handled:

Health check grace period

After launching a new instance, the ASG waits this many seconds before starting health checks. Set it longer than your application’s startup time: typically 60 to 300 seconds depending on how long initialisation takes. Too short and the instance gets replaced before it is ready; too long and genuinely unhealthy instances go undetected for longer than necessary.

Instance warmup

Used by scaling policies. During the warmup period, a newly launched instance is not counted toward the fleet metrics that drive scaling decisions. This prevents the ASG from thinking demand is still high (because new instances have not yet absorbed load) and launching additional instances on top of the ones already launching.

Warm pools

Warm pools let you maintain a set of pre-initialised instances in a stopped or running state, ready to join the live fleet quickly. This is useful when your application has a long initialisation time (loading a large model or pre-caching data) and you cannot afford several minutes of cold start during a scale-out event. Warm pools add cost since you pay for the pre-warmed instances, so they are worth evaluating only when cold start latency is a genuine problem.

Lifecycle hooks

Lifecycle hooks let you pause the launch or termination of an instance to run custom logic before the ASG continues. Two transition points are supported:

  • Launch hook: After the EC2 instance starts but before it is marked in-service, run a script that registers the instance with a service discovery system, waits for data to sync, or completes application warm-up.
  • Terminate hook: Before AWS terminates an instance, drain active connections, archive state to S3, or deregister from external services.

While a lifecycle hook is active, the instance is in a Pending:Wait (launch) or Terminating:Wait (terminate) state. You must complete it by calling complete-lifecycle-action, or it times out after a configurable period (default 1 hour, maximum 48 hours).

# Add a launch lifecycle hook
aws autoscaling put-lifecycle-hook \
  --lifecycle-hook-name warm-up-hook \
  --auto-scaling-group-name production-web-asg \
  --lifecycle-transition autoscaling:EC2_INSTANCE_LAUNCHING \
  --heartbeat-timeout 300 \
  --default-result CONTINUE

# Complete the hook from within your initialisation script or Lambda function
aws autoscaling complete-lifecycle-action \
  --lifecycle-hook-name warm-up-hook \
  --auto-scaling-group-name production-web-asg \
  --instance-id i-0abc12345def67890 \
  --lifecycle-action-result CONTINUE

Instance refresh

When you update a launch template (a new AMI with a security patch, a new instance type, or updated configuration), existing instances in the ASG are not automatically replaced. They continue running the old configuration until they are terminated or replaced. Instance refresh handles the rollout safely: AWS replaces instances in batches, always keeping a minimum percentage of the fleet healthy throughout.

aws autoscaling start-instance-refresh \
  --auto-scaling-group-name production-web-asg \
  --preferences '{
    "MinHealthyPercentage": 80,
    "InstanceWarmup": 120
  }'

With these settings, AWS ensures at least 80% of the fleet stays healthy during the rollout. New instances warm up for 120 seconds before counting toward the healthy total. The refresh completes once all instances have been replaced with the updated launch template version. This is the correct way to deploy AMI changes rather than terminating instances manually and hoping the ASG replaces them correctly.

When to use this

ASGs are a strong fit for:

  • Stateless web applications behind an ALB. The classic pattern. Instances can be replaced freely because no important state is stored on them. Traffic scales with demand without manual intervention.
  • Variable traffic workloads. Any application where load is predictable but variable (e-commerce, SaaS dashboards, APIs) benefits from capacity that scales with it.
  • Production services that need self-healing EC2 capacity. Even without dynamic scaling, an ASG replaces failed instances automatically. You do not need scaling policies to benefit from self-healing behaviour.
  • Environments where manual scaling is too slow or error-prone. If your team manually resizes fleets in response to traffic, ASGs remove that operational burden. See Designing Highly Available Systems for patterns that build on ASGs.
  • Cost-sensitive fleets using mixed Spot capacity. ASGs with mixed On-Demand and Spot instances are the standard way to run large EC2 fleets at reduced cost. See EC2 Cost Optimisation for the full picture.

When not to use this

ASGs are not always the right tool:

  • A single fixed server with stable, low traffic. If you run a small internal tool on one EC2 instance and never expect it to scale, an ASG adds complexity for little benefit. A min=1, max=1 ASG does add self-healing, but a well-monitored single instance is often simpler.
  • Event-driven or short-lived workloads. If your workload is triggered by events and runs briefly, Lambda is likely a better fit. ASGs manage persistent fleets, not ephemeral function invocations. See Choosing Between EC2, Lambda, and Containers for a direct comparison.
  • Container workloads better served by ECS or EKS. If you are running containers, ECS with Fargate or EKS handle scaling at the container level and often require less infrastructure management than ASG-backed EC2 clusters.
  • Highly stateful applications that are hard to replace automatically. If your instances store data locally, hold long-lived connections, or cannot restart cleanly, the self-healing behaviour of an ASG can cause problems. Design your application to be stateless first (see Stateless vs Stateful Services) before relying on automatic instance replacement.

Auto Scaling Group vs a fixed EC2 fleet

Fixed EC2 fleetAuto Scaling Group
ScalingManual. You resize or launch instances yourself.Automatic. Policies and health checks adjust capacity.
ResilienceFailed instances stay down until someone notices.Failed instances are replaced automatically.
Operational overheadHigh. Requires manual monitoring and intervention.Low. AWS manages the fleet continuously.
Cost efficiencyHigher idle cost when over-provisioned; outage risk when under-provisioned.Scales down during quiet periods, reducing waste.
Deployment flexibilityManual AMI updates with riskier rollouts.Instance refresh handles safe rolling deployments.

For most production workloads on EC2, an ASG is strictly better than a fixed fleet. The main exception is a single instance that you intentionally manage by hand. Even then, min=1, max=1 adds self-healing at minimal extra cost.

Common mistakes

Critical: never set min size to 0 in production

If min-size=0, a scale-in event can terminate every instance in the ASG, taking your service completely offline with no instances left to handle traffic. Always set min-size to at least 2 for any production service where availability matters.

  1. Min size too low for production. Setting min=0 means the ASG can terminate all instances during a scale-in event. Setting min=1 leaves no redundancy if that instance fails. Set min to at least 2 for any production service where availability matters.

  2. Missing or incorrect health check grace period. If your application takes 90 seconds to initialise and the grace period is 30 seconds, every new instance will be marked unhealthy and terminated before it is ready, creating an endless replacement loop. Set the grace period comfortably longer than your worst-case startup time.

  3. Single-AZ deployment. An ASG in one subnet provides no protection against AZ failures. AWS AZs are independent failure domains. Spread your ASG across at least two AZs in production. See Regions and Availability Zones for how AZ isolation works.

  4. No application-level health checks for web workloads. EC2 health checks detect hardware failures but do not know whether your application is serving requests correctly. If you are running a web application behind a load balancer, enable ELB health checks so the ASG catches application crashes, not just instance failures. Leaving health check type at “EC2” while using a load balancer means a crashed application stays in rotation until someone notices.

  5. Manually terminating instances instead of changing desired capacity. If you terminate an EC2 instance that belongs to an ASG, the ASG treats it as a failure and immediately launches a replacement. To scale down, reduce the desired capacity and let the ASG choose which instances to terminate gracefully.

  6. Storing important state on replaceable instances. ASG instances can be terminated at any time: during scale-in, instance refresh, or failure replacement. Data stored only on the instance’s local disk is lost when the instance is replaced. Store persistent data in S3, RDS, or EFS; store session state in ElastiCache or DynamoDB.

  7. Forgetting that launch template changes do not update existing instances. Updating a launch template version does not affect running instances. They continue using the configuration they were launched with. To roll out the change, start an instance refresh. Otherwise existing instances run the old configuration indefinitely.

Cost and reliability trade-offs

ASGs can reduce waste by matching capacity to demand, but they do not automatically make systems cheap or safe. A few things to keep in mind:

  • Multi-AZ increases resilience but also cost. Running across two AZs means your minimum fleet must cover both zones. A min=2, 2-AZ setup costs more than a min=1, single-AZ setup. The trade-off is usually worth it for production, but be deliberate about it.
  • Scaling down has a cooldown. Target tracking policies include a scale-in cooldown to prevent rapid back-and-forth scaling. You may run more capacity than strictly needed for a few minutes after demand drops, intentionally, to avoid thrashing.
  • Spot can significantly reduce costs, but adds interruption risk. Mixed capacity with Spot works well for stateless, fault-tolerant workloads. It is not suitable for your minimum guaranteed capacity. See EC2 Spot Instances Explained for how to handle interruptions gracefully.
  • The cheapest design is not always the safest. Setting a very low max capacity to control costs means the ASG cannot scale when you need it most. Size your max based on what your application needs at peak, not on what you want to pay on a quiet day.

For a broader view of keeping EC2 costs under control, see EC2 Cost Optimisation.

Frequently asked questions

What is an Auto Scaling Group?

An Auto Scaling Group (ASG) is a collection of EC2 instances that AWS manages as a fleet. You set a minimum, maximum, and desired instance count. AWS adds instances when demand rises, removes them when demand drops, and replaces any instance that becomes unhealthy with no manual intervention needed.

Do I need a load balancer with an Auto Scaling Group?

No. A load balancer is not always required. ASGs manage EC2 capacity and can replace unhealthy instances without one. However, for web applications serving traffic across multiple instances, attaching an Application Load Balancer gives you a stable entry point, distributes requests evenly, and enables application-level health checks that catch app crashes even when the EC2 instance itself is still running.

What is the difference between min, max, and desired capacity?

Desired capacity is how many instances AWS tries to maintain right now. Min capacity is the floor: the ASG will never go below this number. Max is the ceiling: no scaling policy can exceed it. For example, min=2, max=10, desired=4 means AWS runs four instances, can scale up to ten, and will never drop below two.

What happens when an instance in an Auto Scaling Group becomes unhealthy?

The ASG terminates the unhealthy instance and launches a replacement automatically. With EC2 health checks (the default), AWS detects hardware and system failures. With ELB health checks, the load balancer also detects application-level failures: for example, when your app has crashed but the EC2 instance is still running.

Can I use Spot Instances in an Auto Scaling Group?

Yes. When you use a launch template (not the older launch configuration), ASGs support mixed instance policies that combine On-Demand and Spot capacity in any ratio. This can significantly reduce cost for fault-tolerant or stateless workloads. If AWS reclaims a Spot Instance, the ASG launches a replacement automatically.

Last verified: 1 April 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.