Create AWS Auto Scaling Groups

The aws:autoscaling/group:Group resource, part of the Pulumi AWS provider, defines an Auto Scaling group that maintains a fleet of EC2 instances across availability zones. This guide focuses on four capabilities: launch template integration and versioning, mixed instance policies with spot and on-demand, instance refresh for rolling updates, and warm pools for faster scale-out.

Auto Scaling groups require launch templates or launch configurations, and typically reference VPC subnets, load balancers, and target groups. The examples are intentionally small. Combine them with your own networking, health checks, and scaling policies.

Launch instances from a template version

Most deployments reference a launch template that defines instance configuration, with the version controlling which AMI and settings are used.

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 specifies which template to use and which version. Setting version to “$Latest” ensures new instances always use the most recent template version. The group maintains between minSize and maxSize instances, targeting desiredCapacity.

Mix instance types with weighted capacity

Applications with flexible compute requirements can reduce costs by mixing instance types, with weighted capacity defining how much each type contributes.

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 enables multiple instance types within one group. Each override specifies an instanceType and weightedCapacity. A c4.large with weight 3 counts as three units toward desiredCapacity, while c3.large with weight 2 counts as two units.

Combine spot and on-demand with capacity rebalancing

Workloads that tolerate interruption use spot instances to reduce costs, with capacity rebalancing proactively replacing at-risk 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'

When capacityRebalance is enabled, Auto Scaling monitors spot instance rebalance recommendations and launches replacements before terminations occur. The instancesDistribution block controls the spot/on-demand mix: onDemandBaseCapacity sets a minimum on-demand count, onDemandPercentageAboveBaseCapacity determines the ratio above that base, and spotAllocationStrategy optimizes spot placement.

Override templates for specific instance types

Diverse instance sets sometimes need different configurations per type, such as ARM-specific AMIs for Graviton2 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 example2 = new aws.ec2.LaunchTemplate("example2", {
    namePrefix: "example2",
    imageId: example2AwsAmi.id,
});
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: "c6g.large",
                    launchTemplateSpecification: {
                        launchTemplateId: example2.id,
                    },
                    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")
example2 = aws.ec2.LaunchTemplate("example2",
    name_prefix="example2",
    image_id=example2_aws_ami["id"])
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": "c6g.large",
                    "launch_template_specification": {
                        "launch_template_id": example2.id,
                    },
                    "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
		}
		example2, err := ec2.NewLaunchTemplate(ctx, "example2", &ec2.LaunchTemplateArgs{
			NamePrefix: pulumi.String("example2"),
			ImageId:    pulumi.Any(example2AwsAmi.Id),
		})
		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("c6g.large"),
							LaunchTemplateSpecification: &autoscaling.GroupMixedInstancesPolicyLaunchTemplateOverrideLaunchTemplateSpecificationArgs{
								LaunchTemplateId: example2.ID(),
							},
							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 example2 = new Aws.Ec2.LaunchTemplate("example2", new()
    {
        NamePrefix = "example2",
        ImageId = example2AwsAmi.Id,
    });

    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 = "c6g.large",
                        LaunchTemplateSpecification = new Aws.AutoScaling.Inputs.GroupMixedInstancesPolicyLaunchTemplateOverrideLaunchTemplateSpecificationArgs
                        {
                            LaunchTemplateId = example2.Id,
                        },
                        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 example2 = new LaunchTemplate("example2", LaunchTemplateArgs.builder()
            .namePrefix("example2")
            .imageId(example2AwsAmi.id())
            .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("c6g.large")
                            .launchTemplateSpecification(GroupMixedInstancesPolicyLaunchTemplateOverrideLaunchTemplateSpecificationArgs.builder()
                                .launchTemplateId(example2.id())
                                .build())
                            .weightedCapacity("2")
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ec2:LaunchTemplate
    properties:
      namePrefix: example
      imageId: ${exampleAwsAmi.id}
      instanceType: c5.large
  example2:
    type: aws:ec2:LaunchTemplate
    properties:
      namePrefix: example2
      imageId: ${example2AwsAmi.id}
  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: c6g.large
              launchTemplateSpecification:
                launchTemplateId: ${example2.id}
              weightedCapacity: '2'

When an override includes its own launchTemplateSpecification, that instance type uses a different template than the group’s default. This lets you run x86 and ARM instances in the same group, each with architecture-appropriate AMIs and user data.

Roll out template changes with instance refresh

When you update a launch template, existing instances continue running the old configuration until you trigger an instance refresh.

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 automates rolling replacements. The strategy “Rolling” replaces instances gradually, with minHealthyPercentage ensuring enough capacity remains during the refresh. The triggers list specifies which changes should start a refresh; “tag” means any tag modification triggers replacement.

Pre-initialize instances in a warm pool

Applications with slow startup times can maintain pre-initialized instances that move to InService faster than launching from scratch.

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 defines a pool of pre-initialized instances. The poolState determines their state: “Hibernated” saves memory to disk and stops instances, “Stopped” stops them without hibernation, or “Running” keeps them active. The instanceReusePolicy controls whether instances return to the pool after scale-in.

Beyond these examples

These snippets focus on specific Auto Scaling group features: launch template versioning and mixed instance policies, spot instances with capacity rebalancing, and instance refresh and warm pools. They’re intentionally minimal rather than full scaling solutions.

The examples rely on pre-existing infrastructure such as launch templates with AMI and instance type configuration, VPC subnets when using vpcZoneIdentifiers, and load balancers or target groups when using loadBalancers or targetGroupArns. They focus on configuring the group rather than provisioning everything around it.

To keep things focused, common Auto Scaling patterns are omitted, including:

  • Load balancer attachment (loadBalancers, targetGroupArns)
  • Health check configuration (healthCheckType, healthCheckGracePeriod)
  • Lifecycle hooks and notifications (initialLifecycleHooks)
  • Scaling policies and CloudWatch alarms
  • Placement groups 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 FREE

Frequently Asked Questions

Launch Configuration & Requirements
What's required to create an Auto Scaling Group?
You must specify exactly one of launchConfiguration, launchTemplate, or mixedInstancesPolicy to define how instances are launched.
Why am I getting conflicts with load balancer attachments?
Using the same traffic source in both the ASG resource (loadBalancers, targetGroupArns, or trafficSource) and standalone Attachment resources causes conflicts. Choose one approach and use lifecycle blocks to suppress differences if necessary.
Capacity & Waiting Behavior
How long does Pulumi wait for instances to be ready?
By default, Pulumi waits for minSize (or desiredCapacity if specified) healthy instances before continuing. Instances are considered healthy when they have HealthStatus: "Healthy" and LifecycleState: "InService". The timeout is controlled by waitForCapacityTimeout.
What's the difference between minElbCapacity and waitForElbCapacity?
minElbCapacity waits for instances to be healthy in attached load balancers only during creation. waitForElbCapacity waits on both create and update operations and takes precedence over minElbCapacity.
How do I disable capacity waiting behavior?
Set waitForCapacityTimeout to “0” to skip all capacity waiting behavior.
Why is my ASG creation taking longer than expected?
If ASG creation takes more than a few minutes, check for scaling activity errors. This often indicates problems with the launch configuration, such as incorrect AMI, security group issues, or instance launch failures.
Health Checks & Instance Lifecycle
What's the difference between EC2 and ELB health checks?
Set healthCheckType to “EC2” for basic instance status checks, or “ELB” to use load balancer health checks. Use healthCheckGracePeriod to specify how long (in seconds) to wait after instance launch before starting health checks.
What's the purpose of defaultInstanceWarmup?
defaultInstanceWarmup specifies how long (in seconds) to wait before a newly launched instance contributes to CloudWatch metrics. This allows the instance to finish initializing and reach stable resource consumption before metrics aggregation begins.
Can I add lifecycle hooks when creating an Auto Scaling Group?
Yes, use initialLifecycleHooks to attach lifecycle hooks before instances launch. However, this only works when creating a new ASG. For updates or existing ASGs, use the separate aws.autoscaling.LifecycleHook resource.
Mixed Instances & Spot
How do I use multiple instance types in my Auto Scaling Group?
Use mixedInstancesPolicy with launchTemplate.overrides to specify different instance types and their weightedCapacity values.
How do I use Spot instances with capacity rebalancing?
Set capacityRebalance: true and configure mixedInstancesPolicy.instancesDistribution with onDemandPercentageAboveBaseCapacity and spotAllocationStrategy (e.g., “capacity-optimized”).
Can I use different launch templates for different instance types?
Yes, specify instance-level launchTemplateSpecification within mixedInstancesPolicy.launchTemplate.overrides. This is useful for architecture-specific configurations like Graviton2 instances requiring different AMIs.
How do I select instance types based on compute requirements?
Use instanceRequirements in mixedInstancesPolicy.launchTemplate.overrides to specify requirements like memoryMib.min and vcpuCount.min instead of manually listing instance types.
Configuration & Limitations
What properties can't I change after creating an Auto Scaling Group?
The name and namePrefix properties are immutable. Changing them will force replacement of the ASG.
Why isn't my Auto Scaling Group scaling properly?
Check if you’ve suspended the Launch or Terminate processes in suspendedProcesses. Suspending these critical process types can prevent the ASG from functioning properly.
What does forceDelete do and when should I use it?
forceDelete allows deleting the ASG without waiting for instances to terminate, bypassing the normal draining behavior. Use with caution as it may leave resources dangling.
Should I use availabilityZones or vpcZoneIdentifiers?
These properties conflict with each other. Use vpcZoneIdentifiers (subnet IDs) for VPC deployments, or availabilityZones for launching into default VPC subnets.
Advanced Features
How do I automatically refresh instances when the ASG configuration changes?
Configure instanceRefresh with strategy: "Rolling" and specify triggers (e.g., [“tag”]) to automatically refresh instances when those properties change.
What's a warm pool and how do I use it?
A warm pool pre-initializes instances to reduce scaling time. Configure warmPool with poolState (e.g., “Hibernated”), minSize, and optionally instanceReusePolicy.reuseOnScaleIn: true.

Using a different cloud?

Explore compute guides for other cloud providers: