The aws:autoscaling/group:Group resource, part of the Pulumi AWS provider, defines an Auto Scaling group that manages EC2 instance capacity: launch configuration, size constraints, and scaling behavior. This guide focuses on four capabilities: launch template integration, mixed instances policies with spot and on-demand, instance refresh for configuration rollouts, and warm pools for faster scaling.
Auto Scaling groups require launch templates or launch configurations, run in VPC subnets or availability zones, and often integrate with load balancers and CloudWatch alarms. The examples are intentionally small. Combine them with your own networking, health checks, and scaling policies.
Launch instances from a template version
Most deployments start by defining a launch template that specifies the AMI and instance type, then referencing that template in the Auto Scaling group.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const foobar = new aws.ec2.LaunchTemplate("foobar", {
namePrefix: "foobar",
imageId: "ami-1a2b3c",
instanceType: "t2.micro",
});
const bar = new aws.autoscaling.Group("bar", {
availabilityZones: ["us-east-1a"],
desiredCapacity: 1,
maxSize: 1,
minSize: 1,
launchTemplate: {
id: foobar.id,
version: "$Latest",
},
});
import pulumi
import pulumi_aws as aws
foobar = aws.ec2.LaunchTemplate("foobar",
name_prefix="foobar",
image_id="ami-1a2b3c",
instance_type="t2.micro")
bar = aws.autoscaling.Group("bar",
availability_zones=["us-east-1a"],
desired_capacity=1,
max_size=1,
min_size=1,
launch_template={
"id": foobar.id,
"version": "$Latest",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
foobar, err := ec2.NewLaunchTemplate(ctx, "foobar", &ec2.LaunchTemplateArgs{
NamePrefix: pulumi.String("foobar"),
ImageId: pulumi.String("ami-1a2b3c"),
InstanceType: pulumi.String("t2.micro"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "bar", &autoscaling.GroupArgs{
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-east-1a"),
},
DesiredCapacity: pulumi.Int(1),
MaxSize: pulumi.Int(1),
MinSize: pulumi.Int(1),
LaunchTemplate: &autoscaling.GroupLaunchTemplateArgs{
Id: foobar.ID(),
Version: pulumi.String("$Latest"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var foobar = new Aws.Ec2.LaunchTemplate("foobar", new()
{
NamePrefix = "foobar",
ImageId = "ami-1a2b3c",
InstanceType = "t2.micro",
});
var bar = new Aws.AutoScaling.Group("bar", new()
{
AvailabilityZones = new[]
{
"us-east-1a",
},
DesiredCapacity = 1,
MaxSize = 1,
MinSize = 1,
LaunchTemplate = new Aws.AutoScaling.Inputs.GroupLaunchTemplateArgs
{
Id = foobar.Id,
Version = "$Latest",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupLaunchTemplateArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var foobar = new LaunchTemplate("foobar", LaunchTemplateArgs.builder()
.namePrefix("foobar")
.imageId("ami-1a2b3c")
.instanceType("t2.micro")
.build());
var bar = new Group("bar", GroupArgs.builder()
.availabilityZones("us-east-1a")
.desiredCapacity(1)
.maxSize(1)
.minSize(1)
.launchTemplate(GroupLaunchTemplateArgs.builder()
.id(foobar.id())
.version("$Latest")
.build())
.build());
}
}
resources:
foobar:
type: aws:ec2:LaunchTemplate
properties:
namePrefix: foobar
imageId: ami-1a2b3c
instanceType: t2.micro
bar:
type: aws:autoscaling:Group
properties:
availabilityZones:
- us-east-1a
desiredCapacity: 1
maxSize: 1
minSize: 1
launchTemplate:
id: ${foobar.id}
version: $Latest
The launchTemplate block points to your template by ID and specifies which version to use. The $Latest version ensures new instances always use the most recent template configuration. The capacity properties (minSize, maxSize, desiredCapacity) control how many instances Auto Scaling maintains.
Mix instance types with weighted capacity
Applications that can run on different instance types benefit from mixed instances policies, which let Auto Scaling choose from multiple types to optimize cost and availability.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.ec2.LaunchTemplate("example", {
namePrefix: "example",
imageId: exampleAwsAmi.id,
instanceType: "c5.large",
});
const exampleGroup = new aws.autoscaling.Group("example", {
availabilityZones: ["us-east-1a"],
desiredCapacity: 1,
maxSize: 1,
minSize: 1,
mixedInstancesPolicy: {
launchTemplate: {
launchTemplateSpecification: {
launchTemplateId: example.id,
},
overrides: [
{
instanceType: "c4.large",
weightedCapacity: "3",
},
{
instanceType: "c3.large",
weightedCapacity: "2",
},
],
},
},
});
import pulumi
import pulumi_aws as aws
example = aws.ec2.LaunchTemplate("example",
name_prefix="example",
image_id=example_aws_ami["id"],
instance_type="c5.large")
example_group = aws.autoscaling.Group("example",
availability_zones=["us-east-1a"],
desired_capacity=1,
max_size=1,
min_size=1,
mixed_instances_policy={
"launch_template": {
"launch_template_specification": {
"launch_template_id": example.id,
},
"overrides": [
{
"instance_type": "c4.large",
"weighted_capacity": "3",
},
{
"instance_type": "c3.large",
"weighted_capacity": "2",
},
],
},
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := ec2.NewLaunchTemplate(ctx, "example", &ec2.LaunchTemplateArgs{
NamePrefix: pulumi.String("example"),
ImageId: pulumi.Any(exampleAwsAmi.Id),
InstanceType: pulumi.String("c5.large"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "example", &autoscaling.GroupArgs{
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-east-1a"),
},
DesiredCapacity: pulumi.Int(1),
MaxSize: pulumi.Int(1),
MinSize: pulumi.Int(1),
MixedInstancesPolicy: &autoscaling.GroupMixedInstancesPolicyArgs{
LaunchTemplate: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateArgs{
LaunchTemplateSpecification: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs{
LaunchTemplateId: example.ID(),
},
Overrides: autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArray{
&autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs{
InstanceType: pulumi.String("c4.large"),
WeightedCapacity: pulumi.String("3"),
},
&autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs{
InstanceType: pulumi.String("c3.large"),
WeightedCapacity: pulumi.String("2"),
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Ec2.LaunchTemplate("example", new()
{
NamePrefix = "example",
ImageId = exampleAwsAmi.Id,
InstanceType = "c5.large",
});
var exampleGroup = new Aws.AutoScaling.Group("example", new()
{
AvailabilityZones = new[]
{
"us-east-1a",
},
DesiredCapacity = 1,
MaxSize = 1,
MinSize = 1,
MixedInstancesPolicy = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyArgs
{
LaunchTemplate = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateArgs
{
LaunchTemplateSpecification = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs
{
LaunchTemplateId = example.Id,
},
Overrides = new[]
{
new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs
{
InstanceType = "c4.large",
WeightedCapacity = "3",
},
new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs
{
InstanceType = "c3.large",
WeightedCapacity = "2",
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LaunchTemplate("example", LaunchTemplateArgs.builder()
.namePrefix("example")
.imageId(exampleAwsAmi.id())
.instanceType("c5.large")
.build());
var exampleGroup = new Group("exampleGroup", GroupArgs.builder()
.availabilityZones("us-east-1a")
.desiredCapacity(1)
.maxSize(1)
.minSize(1)
.mixedInstancesPolicy(GroupMixedInstancesPolicyArgs.builder()
.launchTemplate(GroupMixedInstancesPolicyLaunchTemplateArgs.builder()
.launchTemplateSpecification(GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs.builder()
.launchTemplateId(example.id())
.build())
.overrides(
GroupMixedInstancesPolicyLaunchTemplateOverrideArgs.builder()
.instanceType("c4.large")
.weightedCapacity("3")
.build(),
GroupMixedInstancesPolicyLaunchTemplateOverrideArgs.builder()
.instanceType("c3.large")
.weightedCapacity("2")
.build())
.build())
.build())
.build());
}
}
resources:
example:
type: aws:ec2:LaunchTemplate
properties:
namePrefix: example
imageId: ${exampleAwsAmi.id}
instanceType: c5.large
exampleGroup:
type: aws:autoscaling:Group
name: example
properties:
availabilityZones:
- us-east-1a
desiredCapacity: 1
maxSize: 1
minSize: 1
mixedInstancesPolicy:
launchTemplate:
launchTemplateSpecification:
launchTemplateId: ${example.id}
overrides:
- instanceType: c4.large
weightedCapacity: '3'
- instanceType: c3.large
weightedCapacity: '2'
The mixedInstancesPolicy defines a base launch template and a list of instance type overrides. Each override specifies an instance type and weighted capacity, which tells Auto Scaling how much capacity that instance type provides. A c4.large with weight 3 counts as three units of capacity, while a c3.large with weight 2 counts as two units.
Optimize costs with spot instances and rebalancing
Workloads that tolerate interruption can reduce costs by mixing on-demand and spot instances, with capacity rebalancing to proactively replace at-risk spot instances.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.ec2.LaunchTemplate("example", {
namePrefix: "example",
imageId: exampleAwsAmi.id,
instanceType: "c5.large",
});
const exampleGroup = new aws.autoscaling.Group("example", {
capacityRebalance: true,
desiredCapacity: 12,
maxSize: 15,
minSize: 12,
vpcZoneIdentifiers: [
example1.id,
example2.id,
],
mixedInstancesPolicy: {
instancesDistribution: {
onDemandBaseCapacity: 0,
onDemandPercentageAboveBaseCapacity: 25,
spotAllocationStrategy: "capacity-optimized",
},
launchTemplate: {
launchTemplateSpecification: {
launchTemplateId: example.id,
},
overrides: [
{
instanceType: "c4.large",
weightedCapacity: "3",
},
{
instanceType: "c3.large",
weightedCapacity: "2",
},
],
},
},
});
import pulumi
import pulumi_aws as aws
example = aws.ec2.LaunchTemplate("example",
name_prefix="example",
image_id=example_aws_ami["id"],
instance_type="c5.large")
example_group = aws.autoscaling.Group("example",
capacity_rebalance=True,
desired_capacity=12,
max_size=15,
min_size=12,
vpc_zone_identifiers=[
example1["id"],
example2["id"],
],
mixed_instances_policy={
"instances_distribution": {
"on_demand_base_capacity": 0,
"on_demand_percentage_above_base_capacity": 25,
"spot_allocation_strategy": "capacity-optimized",
},
"launch_template": {
"launch_template_specification": {
"launch_template_id": example.id,
},
"overrides": [
{
"instance_type": "c4.large",
"weighted_capacity": "3",
},
{
"instance_type": "c3.large",
"weighted_capacity": "2",
},
],
},
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := ec2.NewLaunchTemplate(ctx, "example", &ec2.LaunchTemplateArgs{
NamePrefix: pulumi.String("example"),
ImageId: pulumi.Any(exampleAwsAmi.Id),
InstanceType: pulumi.String("c5.large"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "example", &autoscaling.GroupArgs{
CapacityRebalance: pulumi.Bool(true),
DesiredCapacity: pulumi.Int(12),
MaxSize: pulumi.Int(15),
MinSize: pulumi.Int(12),
VpcZoneIdentifiers: pulumi.StringArray{
example1.Id,
example2.Id,
},
MixedInstancesPolicy: &autoscaling.GroupMixedInstancesPolicyArgs{
InstancesDistribution: &autoscaling.GroupMixedInstancesPolicyInstancesDistributionArgs{
OnDemandBaseCapacity: pulumi.Int(0),
OnDemandPercentageAboveBaseCapacity: pulumi.Int(25),
SpotAllocationStrategy: pulumi.String("capacity-optimized"),
},
LaunchTemplate: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateArgs{
LaunchTemplateSpecification: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs{
LaunchTemplateId: example.ID(),
},
Overrides: autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArray{
&autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs{
InstanceType: pulumi.String("c4.large"),
WeightedCapacity: pulumi.String("3"),
},
&autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs{
InstanceType: pulumi.String("c3.large"),
WeightedCapacity: pulumi.String("2"),
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Ec2.LaunchTemplate("example", new()
{
NamePrefix = "example",
ImageId = exampleAwsAmi.Id,
InstanceType = "c5.large",
});
var exampleGroup = new Aws.AutoScaling.Group("example", new()
{
CapacityRebalance = true,
DesiredCapacity = 12,
MaxSize = 15,
MinSize = 12,
VpcZoneIdentifiers = new[]
{
example1.Id,
example2.Id,
},
MixedInstancesPolicy = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyArgs
{
InstancesDistribution = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyInstancesDistributionArgs
{
OnDemandBaseCapacity = 0,
OnDemandPercentageAboveBaseCapacity = 25,
SpotAllocationStrategy = "capacity-optimized",
},
LaunchTemplate = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateArgs
{
LaunchTemplateSpecification = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs
{
LaunchTemplateId = example.Id,
},
Overrides = new[]
{
new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs
{
InstanceType = "c4.large",
WeightedCapacity = "3",
},
new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs
{
InstanceType = "c3.large",
WeightedCapacity = "2",
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyInstancesDistributionArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LaunchTemplate("example", LaunchTemplateArgs.builder()
.namePrefix("example")
.imageId(exampleAwsAmi.id())
.instanceType("c5.large")
.build());
var exampleGroup = new Group("exampleGroup", GroupArgs.builder()
.capacityRebalance(true)
.desiredCapacity(12)
.maxSize(15)
.minSize(12)
.vpcZoneIdentifiers(
example1.id(),
example2.id())
.mixedInstancesPolicy(GroupMixedInstancesPolicyArgs.builder()
.instancesDistribution(GroupMixedInstancesPolicyInstancesDistributionArgs.builder()
.onDemandBaseCapacity(0)
.onDemandPercentageAboveBaseCapacity(25)
.spotAllocationStrategy("capacity-optimized")
.build())
.launchTemplate(GroupMixedInstancesPolicyLaunchTemplateArgs.builder()
.launchTemplateSpecification(GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs.builder()
.launchTemplateId(example.id())
.build())
.overrides(
GroupMixedInstancesPolicyLaunchTemplateOverrideArgs.builder()
.instanceType("c4.large")
.weightedCapacity("3")
.build(),
GroupMixedInstancesPolicyLaunchTemplateOverrideArgs.builder()
.instanceType("c3.large")
.weightedCapacity("2")
.build())
.build())
.build())
.build());
}
}
resources:
example:
type: aws:ec2:LaunchTemplate
properties:
namePrefix: example
imageId: ${exampleAwsAmi.id}
instanceType: c5.large
exampleGroup:
type: aws:autoscaling:Group
name: example
properties:
capacityRebalance: true
desiredCapacity: 12
maxSize: 15
minSize: 12
vpcZoneIdentifiers:
- ${example1.id}
- ${example2.id}
mixedInstancesPolicy:
instancesDistribution:
onDemandBaseCapacity: 0
onDemandPercentageAboveBaseCapacity: 25
spotAllocationStrategy: capacity-optimized
launchTemplate:
launchTemplateSpecification:
launchTemplateId: ${example.id}
overrides:
- instanceType: c4.large
weightedCapacity: '3'
- instanceType: c3.large
weightedCapacity: '2'
The instancesDistribution block controls the on-demand and spot mix. Setting onDemandBaseCapacity to 0 and onDemandPercentageAboveBaseCapacity to 25 means 25% of capacity runs on-demand, 75% on spot. The capacityRebalance property enables proactive replacement of spot instances that are at elevated risk of interruption.
Select instances by compute requirements
Instead of manually listing instance types, you can specify compute requirements like minimum memory and vCPU count, letting Auto Scaling choose compatible instances.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.ec2.LaunchTemplate("example", {
namePrefix: "example",
imageId: exampleAwsAmi.id,
instanceType: "c5.large",
});
const exampleGroup = new aws.autoscaling.Group("example", {
availabilityZones: ["us-east-1a"],
desiredCapacity: 1,
maxSize: 1,
minSize: 1,
mixedInstancesPolicy: {
launchTemplate: {
launchTemplateSpecification: {
launchTemplateId: example.id,
},
overrides: [{
instanceRequirements: {
memoryMib: {
min: 1000,
},
vcpuCount: {
min: 4,
},
},
}],
},
},
});
import pulumi
import pulumi_aws as aws
example = aws.ec2.LaunchTemplate("example",
name_prefix="example",
image_id=example_aws_ami["id"],
instance_type="c5.large")
example_group = aws.autoscaling.Group("example",
availability_zones=["us-east-1a"],
desired_capacity=1,
max_size=1,
min_size=1,
mixed_instances_policy={
"launch_template": {
"launch_template_specification": {
"launch_template_id": example.id,
},
"overrides": [{
"instance_requirements": {
"memory_mib": {
"min": 1000,
},
"vcpu_count": {
"min": 4,
},
},
}],
},
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := ec2.NewLaunchTemplate(ctx, "example", &ec2.LaunchTemplateArgs{
NamePrefix: pulumi.String("example"),
ImageId: pulumi.Any(exampleAwsAmi.Id),
InstanceType: pulumi.String("c5.large"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "example", &autoscaling.GroupArgs{
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-east-1a"),
},
DesiredCapacity: pulumi.Int(1),
MaxSize: pulumi.Int(1),
MinSize: pulumi.Int(1),
MixedInstancesPolicy: &autoscaling.GroupMixedInstancesPolicyArgs{
LaunchTemplate: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateArgs{
LaunchTemplateSpecification: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs{
LaunchTemplateId: example.ID(),
},
Overrides: autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArray{
&autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs{
InstanceRequirements: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsArgs{
MemoryMib: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsMemoryMibArgs{
Min: pulumi.Int(1000),
},
VcpuCount: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsVcpuCountArgs{
Min: pulumi.Int(4),
},
},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Ec2.LaunchTemplate("example", new()
{
NamePrefix = "example",
ImageId = exampleAwsAmi.Id,
InstanceType = "c5.large",
});
var exampleGroup = new Aws.AutoScaling.Group("example", new()
{
AvailabilityZones = new[]
{
"us-east-1a",
},
DesiredCapacity = 1,
MaxSize = 1,
MinSize = 1,
MixedInstancesPolicy = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyArgs
{
LaunchTemplate = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateArgs
{
LaunchTemplateSpecification = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs
{
LaunchTemplateId = example.Id,
},
Overrides = new[]
{
new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideArgs
{
InstanceRequirements = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsArgs
{
MemoryMib = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsMemoryMibArgs
{
Min = 1000,
},
VcpuCount = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsVcpuCountArgs
{
Min = 4,
},
},
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateArgs;
import com.pulumi.aws.autoscaling.inputs.GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LaunchTemplate("example", LaunchTemplateArgs.builder()
.namePrefix("example")
.imageId(exampleAwsAmi.id())
.instanceType("c5.large")
.build());
var exampleGroup = new Group("exampleGroup", GroupArgs.builder()
.availabilityZones("us-east-1a")
.desiredCapacity(1)
.maxSize(1)
.minSize(1)
.mixedInstancesPolicy(GroupMixedInstancesPolicyArgs.builder()
.launchTemplate(GroupMixedInstancesPolicyLaunchTemplateArgs.builder()
.launchTemplateSpecification(GroupMixedInstancesPolicyLaunchTemplateLaunchTemplateSpecificationArgs.builder()
.launchTemplateId(example.id())
.build())
.overrides(GroupMixedInstancesPolicyLaunchTemplateOverrideArgs.builder()
.instanceRequirements(GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsArgs.builder()
.memoryMib(GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsMemoryMibArgs.builder()
.min(1000)
.build())
.vcpuCount(GroupMixedInstancesPolicyLaunchTemplateOverrideInstanceRequirementsVcpuCountArgs.builder()
.min(4)
.build())
.build())
.build())
.build())
.build())
.build());
}
}
resources:
example:
type: aws:ec2:LaunchTemplate
properties:
namePrefix: example
imageId: ${exampleAwsAmi.id}
instanceType: c5.large
exampleGroup:
type: aws:autoscaling:Group
name: example
properties:
availabilityZones:
- us-east-1a
desiredCapacity: 1
maxSize: 1
minSize: 1
mixedInstancesPolicy:
launchTemplate:
launchTemplateSpecification:
launchTemplateId: ${example.id}
overrides:
- instanceRequirements:
memoryMib:
min: 1000
vcpuCount:
min: 4
The instanceRequirements block defines minimum memory and vCPU constraints. Auto Scaling selects instance types that meet these requirements, automatically adapting to availability and pricing across the instance catalog. This approach simplifies configuration when you care about compute capacity rather than specific instance families.
Roll out template changes with instance refresh
When you update a launch template, existing instances continue running the old configuration. Instance refresh automates the rollout by gradually replacing instances.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = aws.ec2.getAmi({
mostRecent: true,
owners: ["amazon"],
filters: [{
name: "name",
values: ["amzn-ami-hvm-*-x86_64-gp2"],
}],
});
const exampleLaunchTemplate = new aws.ec2.LaunchTemplate("example", {
imageId: example.then(example => example.id),
instanceType: "t3.nano",
});
const exampleGroup = new aws.autoscaling.Group("example", {
availabilityZones: ["us-east-1a"],
desiredCapacity: 1,
maxSize: 2,
minSize: 1,
launchTemplate: {
id: exampleLaunchTemplate.id,
version: exampleLaunchTemplate.latestVersion,
},
tags: [{
key: "Key",
value: "Value",
propagateAtLaunch: true,
}],
instanceRefresh: {
strategy: "Rolling",
preferences: {
minHealthyPercentage: 50,
},
triggers: ["tag"],
},
});
import pulumi
import pulumi_aws as aws
example = aws.ec2.get_ami(most_recent=True,
owners=["amazon"],
filters=[{
"name": "name",
"values": ["amzn-ami-hvm-*-x86_64-gp2"],
}])
example_launch_template = aws.ec2.LaunchTemplate("example",
image_id=example.id,
instance_type="t3.nano")
example_group = aws.autoscaling.Group("example",
availability_zones=["us-east-1a"],
desired_capacity=1,
max_size=2,
min_size=1,
launch_template={
"id": example_launch_template.id,
"version": example_launch_template.latest_version,
},
tags=[{
"key": "Key",
"value": "Value",
"propagate_at_launch": True,
}],
instance_refresh={
"strategy": "Rolling",
"preferences": {
"min_healthy_percentage": 50,
},
"triggers": ["tag"],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := ec2.LookupAmi(ctx, &ec2.LookupAmiArgs{
MostRecent: pulumi.BoolRef(true),
Owners: []string{
"amazon",
},
Filters: []ec2.GetAmiFilter{
{
Name: "name",
Values: []string{
"amzn-ami-hvm-*-x86_64-gp2",
},
},
},
}, nil)
if err != nil {
return err
}
exampleLaunchTemplate, err := ec2.NewLaunchTemplate(ctx, "example", &ec2.LaunchTemplateArgs{
ImageId: pulumi.String(example.Id),
InstanceType: pulumi.String("t3.nano"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "example", &autoscaling.GroupArgs{
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-east-1a"),
},
DesiredCapacity: pulumi.Int(1),
MaxSize: pulumi.Int(2),
MinSize: pulumi.Int(1),
LaunchTemplate: &autoscaling.GroupLaunchTemplateArgs{
Id: exampleLaunchTemplate.ID(),
Version: exampleLaunchTemplate.LatestVersion,
},
Tags: autoscaling.GroupTagArray{
&autoscaling.GroupTagArgs{
Key: pulumi.String("Key"),
Value: pulumi.String("Value"),
PropagateAtLaunch: pulumi.Bool(true),
},
},
InstanceRefresh: &autoscaling.GroupInstanceRefreshArgs{
Strategy: pulumi.String("Rolling"),
Preferences: &autoscaling.GroupInstanceRefreshPreferencesArgs{
MinHealthyPercentage: pulumi.Int(50),
},
Triggers: pulumi.StringArray{
pulumi.String("tag"),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = Aws.Ec2.GetAmi.Invoke(new()
{
MostRecent = true,
Owners = new[]
{
"amazon",
},
Filters = new[]
{
new Aws.Ec2.Inputs.GetAmiFilterInputArgs
{
Name = "name",
Values = new[]
{
"amzn-ami-hvm-*-x86_64-gp2",
},
},
},
});
var exampleLaunchTemplate = new Aws.Ec2.LaunchTemplate("example", new()
{
ImageId = example.Apply(getAmiResult => getAmiResult.Id),
InstanceType = "t3.nano",
});
var exampleGroup = new Aws.AutoScaling.Group("example", new()
{
AvailabilityZones = new[]
{
"us-east-1a",
},
DesiredCapacity = 1,
MaxSize = 2,
MinSize = 1,
LaunchTemplate = new Aws.AutoScaling.Inputs.GroupLaunchTemplateArgs
{
Id = exampleLaunchTemplate.Id,
Version = exampleLaunchTemplate.LatestVersion,
},
Tags = new[]
{
new Aws.AutoScaling.Inputs.GroupTagArgs
{
Key = "Key",
Value = "Value",
PropagateAtLaunch = true,
},
},
InstanceRefresh = new Aws.AutoScaling.Inputs.GroupInstanceRefreshArgs
{
Strategy = "Rolling",
Preferences = new Aws.AutoScaling.Inputs.GroupInstanceRefreshPreferencesArgs
{
MinHealthyPercentage = 50,
},
Triggers = new[]
{
"tag",
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Ec2Functions;
import com.pulumi.aws.ec2.inputs.GetAmiArgs;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupLaunchTemplateArgs;
import com.pulumi.aws.autoscaling.inputs.GroupTagArgs;
import com.pulumi.aws.autoscaling.inputs.GroupInstanceRefreshArgs;
import com.pulumi.aws.autoscaling.inputs.GroupInstanceRefreshPreferencesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var example = Ec2Functions.getAmi(GetAmiArgs.builder()
.mostRecent(true)
.owners("amazon")
.filters(GetAmiFilterArgs.builder()
.name("name")
.values("amzn-ami-hvm-*-x86_64-gp2")
.build())
.build());
var exampleLaunchTemplate = new LaunchTemplate("exampleLaunchTemplate", LaunchTemplateArgs.builder()
.imageId(example.id())
.instanceType("t3.nano")
.build());
var exampleGroup = new Group("exampleGroup", GroupArgs.builder()
.availabilityZones("us-east-1a")
.desiredCapacity(1)
.maxSize(2)
.minSize(1)
.launchTemplate(GroupLaunchTemplateArgs.builder()
.id(exampleLaunchTemplate.id())
.version(exampleLaunchTemplate.latestVersion())
.build())
.tags(GroupTagArgs.builder()
.key("Key")
.value("Value")
.propagateAtLaunch(true)
.build())
.instanceRefresh(GroupInstanceRefreshArgs.builder()
.strategy("Rolling")
.preferences(GroupInstanceRefreshPreferencesArgs.builder()
.minHealthyPercentage(50)
.build())
.triggers("tag")
.build())
.build());
}
}
resources:
exampleGroup:
type: aws:autoscaling:Group
name: example
properties:
availabilityZones:
- us-east-1a
desiredCapacity: 1
maxSize: 2
minSize: 1
launchTemplate:
id: ${exampleLaunchTemplate.id}
version: ${exampleLaunchTemplate.latestVersion}
tags:
- key: Key
value: Value
propagateAtLaunch: true
instanceRefresh:
strategy: Rolling
preferences:
minHealthyPercentage: 50
triggers:
- tag
exampleLaunchTemplate:
type: aws:ec2:LaunchTemplate
name: example
properties:
imageId: ${example.id}
instanceType: t3.nano
variables:
example:
fn::invoke:
function: aws:ec2:getAmi
arguments:
mostRecent: true
owners:
- amazon
filters:
- name: name
values:
- amzn-ami-hvm-*-x86_64-gp2
The instanceRefresh block defines how updates roll out. The Rolling strategy replaces instances in batches, maintaining at least minHealthyPercentage of capacity throughout the refresh. The triggers property lists which changes should start a refresh; here, tag changes trigger automatic rollouts.
Pre-initialize instances in a warm pool
Applications with slow startup times can maintain a pool of pre-initialized instances that are ready to enter service quickly when scaling events occur.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.ec2.LaunchTemplate("example", {
namePrefix: "example",
imageId: exampleAwsAmi.id,
instanceType: "c5.large",
});
const exampleGroup = new aws.autoscaling.Group("example", {
availabilityZones: ["us-east-1a"],
desiredCapacity: 1,
maxSize: 5,
minSize: 1,
warmPool: {
poolState: "Hibernated",
minSize: 1,
maxGroupPreparedCapacity: 10,
instanceReusePolicy: {
reuseOnScaleIn: true,
},
},
});
import pulumi
import pulumi_aws as aws
example = aws.ec2.LaunchTemplate("example",
name_prefix="example",
image_id=example_aws_ami["id"],
instance_type="c5.large")
example_group = aws.autoscaling.Group("example",
availability_zones=["us-east-1a"],
desired_capacity=1,
max_size=5,
min_size=1,
warm_pool={
"pool_state": "Hibernated",
"min_size": 1,
"max_group_prepared_capacity": 10,
"instance_reuse_policy": {
"reuse_on_scale_in": True,
},
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/autoscaling"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := ec2.NewLaunchTemplate(ctx, "example", &ec2.LaunchTemplateArgs{
NamePrefix: pulumi.String("example"),
ImageId: pulumi.Any(exampleAwsAmi.Id),
InstanceType: pulumi.String("c5.large"),
})
if err != nil {
return err
}
_, err = autoscaling.NewGroup(ctx, "example", &autoscaling.GroupArgs{
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-east-1a"),
},
DesiredCapacity: pulumi.Int(1),
MaxSize: pulumi.Int(5),
MinSize: pulumi.Int(1),
WarmPool: &autoscaling.GroupWarmPoolArgs{
PoolState: pulumi.String("Hibernated"),
MinSize: pulumi.Int(1),
MaxGroupPreparedCapacity: pulumi.Int(10),
InstanceReusePolicy: &autoscaling.GroupWarmPoolInstanceReusePolicyArgs{
ReuseOnScaleIn: pulumi.Bool(true),
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Ec2.LaunchTemplate("example", new()
{
NamePrefix = "example",
ImageId = exampleAwsAmi.Id,
InstanceType = "c5.large",
});
var exampleGroup = new Aws.AutoScaling.Group("example", new()
{
AvailabilityZones = new[]
{
"us-east-1a",
},
DesiredCapacity = 1,
MaxSize = 5,
MinSize = 1,
WarmPool = new Aws.AutoScaling.Inputs.GroupWarmPoolArgs
{
PoolState = "Hibernated",
MinSize = 1,
MaxGroupPreparedCapacity = 10,
InstanceReusePolicy = new Aws.AutoScaling.Inputs.GroupWarmPoolInstanceReusePolicyArgs
{
ReuseOnScaleIn = true,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.autoscaling.Group;
import com.pulumi.aws.autoscaling.GroupArgs;
import com.pulumi.aws.autoscaling.inputs.GroupWarmPoolArgs;
import com.pulumi.aws.autoscaling.inputs.GroupWarmPoolInstanceReusePolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LaunchTemplate("example", LaunchTemplateArgs.builder()
.namePrefix("example")
.imageId(exampleAwsAmi.id())
.instanceType("c5.large")
.build());
var exampleGroup = new Group("exampleGroup", GroupArgs.builder()
.availabilityZones("us-east-1a")
.desiredCapacity(1)
.maxSize(5)
.minSize(1)
.warmPool(GroupWarmPoolArgs.builder()
.poolState("Hibernated")
.minSize(1)
.maxGroupPreparedCapacity(10)
.instanceReusePolicy(GroupWarmPoolInstanceReusePolicyArgs.builder()
.reuseOnScaleIn(true)
.build())
.build())
.build());
}
}
resources:
example:
type: aws:ec2:LaunchTemplate
properties:
namePrefix: example
imageId: ${exampleAwsAmi.id}
instanceType: c5.large
exampleGroup:
type: aws:autoscaling:Group
name: example
properties:
availabilityZones:
- us-east-1a
desiredCapacity: 1
maxSize: 5
minSize: 1
warmPool:
poolState: Hibernated
minSize: 1
maxGroupPreparedCapacity: 10
instanceReusePolicy:
reuseOnScaleIn: true
The warmPool block configures a pool of instances that are stopped or hibernated until needed. The poolState determines whether instances are stopped or hibernated. The instanceReusePolicy controls whether instances return to the warm pool when scaling in, reducing initialization overhead for future scale-out events.
Beyond these examples
These snippets focus on specific Auto Scaling group features: launch templates and mixed instances policies, spot instances and capacity rebalancing, and instance refresh and warm pools. They’re intentionally minimal rather than full scaling solutions.
The examples may reference pre-existing infrastructure such as launch templates with AMI and instance configuration, VPC subnets for instance placement, and IAM roles for lifecycle hooks. They focus on configuring the Auto Scaling group rather than provisioning everything around it.
To keep things focused, common Auto Scaling patterns are omitted, including:
- Load balancer integration (loadBalancers, targetGroupArns)
- Health check configuration (healthCheckType, healthCheckGracePeriod)
- Scaling policies and CloudWatch alarms
- Lifecycle hooks for custom instance initialization
- Placement groups and availability zone distribution
- Termination policies and instance protection
These omissions are intentional: the goal is to illustrate how each Auto Scaling feature is wired, not provide drop-in scaling modules. See the Auto Scaling Group resource reference for all available configuration options.
Let's create AWS Auto Scaling Groups
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Launch Configuration & Instance Types
launchConfiguration (legacy), launchTemplate (recommended), or mixedInstancesPolicy (for mixing spot and on-demand instances).launchTemplate.version to $Latest to automatically use the most recent version.mixedInstancesPolicy with instancesDistribution to configure the spot allocation strategy and on-demand percentage. Enable capacityRebalance to handle spot interruptions gracefully.mixedInstancesPolicy.launchTemplate.overrides with instanceRequirements to specify memory and vCPU constraints rather than exact instance types.Networking & Availability Zones
availabilityZones to launch into default VPC subnets, or vpcZoneIdentifiers to specify exact subnet IDs (recommended for most use cases).Capacity & Scaling
minSize (or desiredCapacity if specified) healthy instances before continuing. Instances are considered healthy when they report HealthStatus: "Healthy" and LifecycleState: "InService". Set waitForCapacityTimeout to “0” to skip this waiting behavior.minElbCapacity to wait for a minimum number of healthy instances in ELBs on creation only, or waitForElbCapacity to wait for an exact number on both create and update operations. waitForElbCapacity takes precedence over minElbCapacity.instanceRefresh with a strategy like “Rolling” and specify triggers (e.g., “tag”) to automatically refresh instances when certain properties change.Load Balancer Integration
loadBalancers, targetGroupArns, trafficSource) and standalone Attachment resources causes conflicts. Choose one approach: manage attachments inline with the ASG or use standalone resources, not both.Lifecycle & Maintenance
initialLifecycleHooks only works when creating a new Auto Scaling Group. For updates or other use cases, use the standalone aws.autoscaling.LifecycleHook resource instead.Launch or Terminate process types can prevent your Auto Scaling Group from functioning properly. Only suspend these processes if absolutely necessary.forceDelete to true to bypass this behavior and delete immediately, though this may leave resources dangling.