Create AWS EC2 Spot Fleet Requests

The aws:ec2/spotFleetRequest:SpotFleetRequest resource, part of the Pulumi AWS provider, defines a Spot Fleet request that provisions multiple Spot instances across instance types, availability zones, and price points. This guide focuses on three capabilities: launch specifications vs launch templates, allocation strategies, and multi-subnet placement.

Spot Fleet requests require IAM fleet roles, reference VPC subnets, and use AMIs that exist in your region. AWS strongly discourages this legacy API; consider EC2 Fleet or Auto Scaling Groups for new projects. The examples are intentionally small. Combine them with your own IAM roles, VPC infrastructure, and capacity planning.

Request capacity across instance types and markets

Spot Fleet requests let you define multiple launch specifications, each targeting different instance types, zones, or price points.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Request a Spot fleet
const cheapCompute = new aws.ec2.SpotFleetRequest("cheap_compute", {
    iamFleetRole: "arn:aws:iam::12345678:role/spot-fleet",
    spotPrice: "0.03",
    allocationStrategy: "diversified",
    targetCapacity: 6,
    validUntil: "2019-11-04T20:44:20Z",
    launchSpecifications: [
        {
            instanceType: "m4.10xlarge",
            ami: "ami-1234",
            spotPrice: "2.793",
            placementTenancy: "dedicated",
            iamInstanceProfileArn: example.arn,
        },
        {
            instanceType: "m4.4xlarge",
            ami: "ami-5678",
            keyName: "my-key",
            spotPrice: "1.117",
            iamInstanceProfileArn: example.arn,
            availabilityZone: "us-west-1a",
            subnetId: "subnet-1234",
            weightedCapacity: "35",
            rootBlockDevices: [{
                volumeSize: 300,
                volumeType: "gp2",
            }],
            tags: {
                Name: "spot-fleet-example",
            },
        },
    ],
});
import pulumi
import pulumi_aws as aws

# Request a Spot fleet
cheap_compute = aws.ec2.SpotFleetRequest("cheap_compute",
    iam_fleet_role="arn:aws:iam::12345678:role/spot-fleet",
    spot_price="0.03",
    allocation_strategy="diversified",
    target_capacity=6,
    valid_until="2019-11-04T20:44:20Z",
    launch_specifications=[
        {
            "instance_type": "m4.10xlarge",
            "ami": "ami-1234",
            "spot_price": "2.793",
            "placement_tenancy": "dedicated",
            "iam_instance_profile_arn": example["arn"],
        },
        {
            "instance_type": "m4.4xlarge",
            "ami": "ami-5678",
            "key_name": "my-key",
            "spot_price": "1.117",
            "iam_instance_profile_arn": example["arn"],
            "availability_zone": "us-west-1a",
            "subnet_id": "subnet-1234",
            "weighted_capacity": "35",
            "root_block_devices": [{
                "volume_size": 300,
                "volume_type": "gp2",
            }],
            "tags": {
                "Name": "spot-fleet-example",
            },
        },
    ])
package main

import (
	"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 {
		// Request a Spot fleet
		_, err := ec2.NewSpotFleetRequest(ctx, "cheap_compute", &ec2.SpotFleetRequestArgs{
			IamFleetRole:       pulumi.String("arn:aws:iam::12345678:role/spot-fleet"),
			SpotPrice:          pulumi.String("0.03"),
			AllocationStrategy: pulumi.String("diversified"),
			TargetCapacity:     pulumi.Int(6),
			ValidUntil:         pulumi.String("2019-11-04T20:44:20Z"),
			LaunchSpecifications: ec2.SpotFleetRequestLaunchSpecificationArray{
				&ec2.SpotFleetRequestLaunchSpecificationArgs{
					InstanceType:          pulumi.String("m4.10xlarge"),
					Ami:                   pulumi.String("ami-1234"),
					SpotPrice:             pulumi.String("2.793"),
					PlacementTenancy:      pulumi.String("dedicated"),
					IamInstanceProfileArn: pulumi.Any(example.Arn),
				},
				&ec2.SpotFleetRequestLaunchSpecificationArgs{
					InstanceType:          pulumi.String("m4.4xlarge"),
					Ami:                   pulumi.String("ami-5678"),
					KeyName:               pulumi.String("my-key"),
					SpotPrice:             pulumi.String("1.117"),
					IamInstanceProfileArn: pulumi.Any(example.Arn),
					AvailabilityZone:      pulumi.String("us-west-1a"),
					SubnetId:              pulumi.String("subnet-1234"),
					WeightedCapacity:      pulumi.String("35"),
					RootBlockDevices: ec2.SpotFleetRequestLaunchSpecificationRootBlockDeviceArray{
						&ec2.SpotFleetRequestLaunchSpecificationRootBlockDeviceArgs{
							VolumeSize: pulumi.Int(300),
							VolumeType: pulumi.String("gp2"),
						},
					},
					Tags: pulumi.StringMap{
						"Name": pulumi.String("spot-fleet-example"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    // Request a Spot fleet
    var cheapCompute = new Aws.Ec2.SpotFleetRequest("cheap_compute", new()
    {
        IamFleetRole = "arn:aws:iam::12345678:role/spot-fleet",
        SpotPrice = "0.03",
        AllocationStrategy = "diversified",
        TargetCapacity = 6,
        ValidUntil = "2019-11-04T20:44:20Z",
        LaunchSpecifications = new[]
        {
            new Aws.Ec2.Inputs.SpotFleetRequestLaunchSpecificationArgs
            {
                InstanceType = "m4.10xlarge",
                Ami = "ami-1234",
                SpotPrice = "2.793",
                PlacementTenancy = "dedicated",
                IamInstanceProfileArn = example.Arn,
            },
            new Aws.Ec2.Inputs.SpotFleetRequestLaunchSpecificationArgs
            {
                InstanceType = "m4.4xlarge",
                Ami = "ami-5678",
                KeyName = "my-key",
                SpotPrice = "1.117",
                IamInstanceProfileArn = example.Arn,
                AvailabilityZone = "us-west-1a",
                SubnetId = "subnet-1234",
                WeightedCapacity = "35",
                RootBlockDevices = new[]
                {
                    new Aws.Ec2.Inputs.SpotFleetRequestLaunchSpecificationRootBlockDeviceArgs
                    {
                        VolumeSize = 300,
                        VolumeType = "gp2",
                    },
                },
                Tags = 
                {
                    { "Name", "spot-fleet-example" },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.SpotFleetRequest;
import com.pulumi.aws.ec2.SpotFleetRequestArgs;
import com.pulumi.aws.ec2.inputs.SpotFleetRequestLaunchSpecificationArgs;
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) {
        // Request a Spot fleet
        var cheapCompute = new SpotFleetRequest("cheapCompute", SpotFleetRequestArgs.builder()
            .iamFleetRole("arn:aws:iam::12345678:role/spot-fleet")
            .spotPrice("0.03")
            .allocationStrategy("diversified")
            .targetCapacity(6)
            .validUntil("2019-11-04T20:44:20Z")
            .launchSpecifications(            
                SpotFleetRequestLaunchSpecificationArgs.builder()
                    .instanceType("m4.10xlarge")
                    .ami("ami-1234")
                    .spotPrice("2.793")
                    .placementTenancy("dedicated")
                    .iamInstanceProfileArn(example.arn())
                    .build(),
                SpotFleetRequestLaunchSpecificationArgs.builder()
                    .instanceType("m4.4xlarge")
                    .ami("ami-5678")
                    .keyName("my-key")
                    .spotPrice("1.117")
                    .iamInstanceProfileArn(example.arn())
                    .availabilityZone("us-west-1a")
                    .subnetId("subnet-1234")
                    .weightedCapacity("35")
                    .rootBlockDevices(SpotFleetRequestLaunchSpecificationRootBlockDeviceArgs.builder()
                        .volumeSize(300)
                        .volumeType("gp2")
                        .build())
                    .tags(Map.of("Name", "spot-fleet-example"))
                    .build())
            .build());

    }
}
resources:
  # Request a Spot fleet
  cheapCompute:
    type: aws:ec2:SpotFleetRequest
    name: cheap_compute
    properties:
      iamFleetRole: arn:aws:iam::12345678:role/spot-fleet
      spotPrice: '0.03'
      allocationStrategy: diversified
      targetCapacity: 6
      validUntil: 2019-11-04T20:44:20Z
      launchSpecifications:
        - instanceType: m4.10xlarge
          ami: ami-1234
          spotPrice: '2.793'
          placementTenancy: dedicated
          iamInstanceProfileArn: ${example.arn}
        - instanceType: m4.4xlarge
          ami: ami-5678
          keyName: my-key
          spotPrice: '1.117'
          iamInstanceProfileArn: ${example.arn}
          availabilityZone: us-west-1a
          subnetId: subnet-1234
          weightedCapacity: 35
          rootBlockDevices:
            - volumeSize: '300'
              volumeType: gp2
          tags:
            Name: spot-fleet-example

The launchSpecifications array defines each configuration option: instance type, AMI, spot price, and placement. The allocationStrategy property controls how the fleet distributes your targetCapacity across these options. The “diversified” strategy spreads capacity to reduce interruption risk. The iamFleetRole grants permissions to launch and terminate instances on your behalf.

Use launch templates for standardized configuration

Launch templates centralize instance configuration that can be versioned and reused across fleets.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const foo = new aws.ec2.LaunchTemplate("foo", {
    name: "launch-template",
    imageId: "ami-516b9131",
    instanceType: "m1.small",
    keyName: "some-key",
});
const fooSpotFleetRequest = new aws.ec2.SpotFleetRequest("foo", {
    iamFleetRole: "arn:aws:iam::12345678:role/spot-fleet",
    spotPrice: "0.005",
    targetCapacity: 2,
    validUntil: "2019-11-04T20:44:20Z",
    launchTemplateConfigs: [{
        launchTemplateSpecification: {
            id: foo.id,
            version: foo.latestVersion,
        },
    }],
}, {
    dependsOn: [test_attach],
});
import pulumi
import pulumi_aws as aws

foo = aws.ec2.LaunchTemplate("foo",
    name="launch-template",
    image_id="ami-516b9131",
    instance_type="m1.small",
    key_name="some-key")
foo_spot_fleet_request = aws.ec2.SpotFleetRequest("foo",
    iam_fleet_role="arn:aws:iam::12345678:role/spot-fleet",
    spot_price="0.005",
    target_capacity=2,
    valid_until="2019-11-04T20:44:20Z",
    launch_template_configs=[{
        "launch_template_specification": {
            "id": foo.id,
            "version": foo.latest_version,
        },
    }],
    opts = pulumi.ResourceOptions(depends_on=[test_attach]))
package main

import (
	"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 {
		foo, err := ec2.NewLaunchTemplate(ctx, "foo", &ec2.LaunchTemplateArgs{
			Name:         pulumi.String("launch-template"),
			ImageId:      pulumi.String("ami-516b9131"),
			InstanceType: pulumi.String("m1.small"),
			KeyName:      pulumi.String("some-key"),
		})
		if err != nil {
			return err
		}
		_, err = ec2.NewSpotFleetRequest(ctx, "foo", &ec2.SpotFleetRequestArgs{
			IamFleetRole:   pulumi.String("arn:aws:iam::12345678:role/spot-fleet"),
			SpotPrice:      pulumi.String("0.005"),
			TargetCapacity: pulumi.Int(2),
			ValidUntil:     pulumi.String("2019-11-04T20:44:20Z"),
			LaunchTemplateConfigs: ec2.SpotFleetRequestLaunchTemplateConfigArray{
				&ec2.SpotFleetRequestLaunchTemplateConfigArgs{
					LaunchTemplateSpecification: &ec2.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs{
						Id:      foo.ID(),
						Version: foo.LatestVersion,
					},
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			test_attach,
		}))
		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 foo = new Aws.Ec2.LaunchTemplate("foo", new()
    {
        Name = "launch-template",
        ImageId = "ami-516b9131",
        InstanceType = "m1.small",
        KeyName = "some-key",
    });

    var fooSpotFleetRequest = new Aws.Ec2.SpotFleetRequest("foo", new()
    {
        IamFleetRole = "arn:aws:iam::12345678:role/spot-fleet",
        SpotPrice = "0.005",
        TargetCapacity = 2,
        ValidUntil = "2019-11-04T20:44:20Z",
        LaunchTemplateConfigs = new[]
        {
            new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigArgs
            {
                LaunchTemplateSpecification = new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs
                {
                    Id = foo.Id,
                    Version = foo.LatestVersion,
                },
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            test_attach,
        },
    });

});
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.ec2.SpotFleetRequest;
import com.pulumi.aws.ec2.SpotFleetRequestArgs;
import com.pulumi.aws.ec2.inputs.SpotFleetRequestLaunchTemplateConfigArgs;
import com.pulumi.aws.ec2.inputs.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs;
import com.pulumi.resources.CustomResourceOptions;
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 foo = new LaunchTemplate("foo", LaunchTemplateArgs.builder()
            .name("launch-template")
            .imageId("ami-516b9131")
            .instanceType("m1.small")
            .keyName("some-key")
            .build());

        var fooSpotFleetRequest = new SpotFleetRequest("fooSpotFleetRequest", SpotFleetRequestArgs.builder()
            .iamFleetRole("arn:aws:iam::12345678:role/spot-fleet")
            .spotPrice("0.005")
            .targetCapacity(2)
            .validUntil("2019-11-04T20:44:20Z")
            .launchTemplateConfigs(SpotFleetRequestLaunchTemplateConfigArgs.builder()
                .launchTemplateSpecification(SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs.builder()
                    .id(foo.id())
                    .version(foo.latestVersion())
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(test_attach)
                .build());

    }
}
resources:
  foo:
    type: aws:ec2:LaunchTemplate
    properties:
      name: launch-template
      imageId: ami-516b9131
      instanceType: m1.small
      keyName: some-key
  fooSpotFleetRequest:
    type: aws:ec2:SpotFleetRequest
    name: foo
    properties:
      iamFleetRole: arn:aws:iam::12345678:role/spot-fleet
      spotPrice: '0.005'
      targetCapacity: 2
      validUntil: 2019-11-04T20:44:20Z
      launchTemplateConfigs:
        - launchTemplateSpecification:
            id: ${foo.id}
            version: ${foo.latestVersion}
    options:
      dependsOn:
        - ${["test-attach"]}

The launchTemplateConfigs property references a launch template by id and version. This separates instance configuration (AMI, instance type, key pairs) from fleet-level settings (capacity, allocation strategy). Launch templates support versioning, making it easier to roll out configuration changes.

Distribute capacity across multiple subnets

When you need instances spread across availability zones, launch template overrides let you specify different subnets for each portion of your fleet.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = aws.ec2.getSubnets({
    filters: [{
        name: "vpc-id",
        values: [vpcId],
    }],
});
const foo = new aws.ec2.LaunchTemplate("foo", {
    name: "launch-template",
    imageId: "ami-516b9131",
    instanceType: "m1.small",
    keyName: "some-key",
});
const fooSpotFleetRequest = new aws.ec2.SpotFleetRequest("foo", {
    iamFleetRole: "arn:aws:iam::12345678:role/spot-fleet",
    spotPrice: "0.005",
    targetCapacity: 2,
    validUntil: "2019-11-04T20:44:20Z",
    launchTemplateConfigs: [{
        launchTemplateSpecification: {
            id: foo.id,
            version: foo.latestVersion,
        },
        overrides: [
            {
                subnetId: example.then(example => example.ids?.[0]),
            },
            {
                subnetId: example.then(example => example.ids?.[1]),
            },
            {
                subnetId: example.then(example => example.ids?.[2]),
            },
        ],
    }],
}, {
    dependsOn: [test_attach],
});
import pulumi
import pulumi_aws as aws

example = aws.ec2.get_subnets(filters=[{
    "name": "vpc-id",
    "values": [vpc_id],
}])
foo = aws.ec2.LaunchTemplate("foo",
    name="launch-template",
    image_id="ami-516b9131",
    instance_type="m1.small",
    key_name="some-key")
foo_spot_fleet_request = aws.ec2.SpotFleetRequest("foo",
    iam_fleet_role="arn:aws:iam::12345678:role/spot-fleet",
    spot_price="0.005",
    target_capacity=2,
    valid_until="2019-11-04T20:44:20Z",
    launch_template_configs=[{
        "launch_template_specification": {
            "id": foo.id,
            "version": foo.latest_version,
        },
        "overrides": [
            {
                "subnet_id": example.ids[0],
            },
            {
                "subnet_id": example.ids[1],
            },
            {
                "subnet_id": example.ids[2],
            },
        ],
    }],
    opts = pulumi.ResourceOptions(depends_on=[test_attach]))
package main

import (
	"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.GetSubnets(ctx, &ec2.GetSubnetsArgs{
Filters: []ec2.GetSubnetsFilter{
{
Name: "vpc-id",
Values: interface{}{
vpcId,
},
},
},
}, nil);
if err != nil {
return err
}
foo, err := ec2.NewLaunchTemplate(ctx, "foo", &ec2.LaunchTemplateArgs{
Name: pulumi.String("launch-template"),
ImageId: pulumi.String("ami-516b9131"),
InstanceType: pulumi.String("m1.small"),
KeyName: pulumi.String("some-key"),
})
if err != nil {
return err
}
_, err = ec2.NewSpotFleetRequest(ctx, "foo", &ec2.SpotFleetRequestArgs{
IamFleetRole: pulumi.String("arn:aws:iam::12345678:role/spot-fleet"),
SpotPrice: pulumi.String("0.005"),
TargetCapacity: pulumi.Int(2),
ValidUntil: pulumi.String("2019-11-04T20:44:20Z"),
LaunchTemplateConfigs: ec2.SpotFleetRequestLaunchTemplateConfigArray{
&ec2.SpotFleetRequestLaunchTemplateConfigArgs{
LaunchTemplateSpecification: &ec2.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs{
Id: foo.ID(),
Version: foo.LatestVersion,
},
Overrides: ec2.SpotFleetRequestLaunchTemplateConfigOverrideArray{
&ec2.SpotFleetRequestLaunchTemplateConfigOverrideArgs{
SubnetId: pulumi.String(example.Ids[0]),
},
&ec2.SpotFleetRequestLaunchTemplateConfigOverrideArgs{
SubnetId: pulumi.String(example.Ids[1]),
},
&ec2.SpotFleetRequestLaunchTemplateConfigOverrideArgs{
SubnetId: pulumi.String(example.Ids[2]),
},
},
},
},
}, pulumi.DependsOn([]pulumi.Resource{
test_attach,
}))
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.GetSubnets.Invoke(new()
    {
        Filters = new[]
        {
            new Aws.Ec2.Inputs.GetSubnetsFilterInputArgs
            {
                Name = "vpc-id",
                Values = new[]
                {
                    vpcId,
                },
            },
        },
    });

    var foo = new Aws.Ec2.LaunchTemplate("foo", new()
    {
        Name = "launch-template",
        ImageId = "ami-516b9131",
        InstanceType = "m1.small",
        KeyName = "some-key",
    });

    var fooSpotFleetRequest = new Aws.Ec2.SpotFleetRequest("foo", new()
    {
        IamFleetRole = "arn:aws:iam::12345678:role/spot-fleet",
        SpotPrice = "0.005",
        TargetCapacity = 2,
        ValidUntil = "2019-11-04T20:44:20Z",
        LaunchTemplateConfigs = new[]
        {
            new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigArgs
            {
                LaunchTemplateSpecification = new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs
                {
                    Id = foo.Id,
                    Version = foo.LatestVersion,
                },
                Overrides = new[]
                {
                    new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigOverrideArgs
                    {
                        SubnetId = example.Apply(getSubnetsResult => getSubnetsResult.Ids[0]),
                    },
                    new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigOverrideArgs
                    {
                        SubnetId = example.Apply(getSubnetsResult => getSubnetsResult.Ids[1]),
                    },
                    new Aws.Ec2.Inputs.SpotFleetRequestLaunchTemplateConfigOverrideArgs
                    {
                        SubnetId = example.Apply(getSubnetsResult => getSubnetsResult.Ids[2]),
                    },
                },
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            test_attach,
        },
    });

});
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.GetSubnetsArgs;
import com.pulumi.aws.ec2.LaunchTemplate;
import com.pulumi.aws.ec2.LaunchTemplateArgs;
import com.pulumi.aws.ec2.SpotFleetRequest;
import com.pulumi.aws.ec2.SpotFleetRequestArgs;
import com.pulumi.aws.ec2.inputs.SpotFleetRequestLaunchTemplateConfigArgs;
import com.pulumi.aws.ec2.inputs.SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs;
import com.pulumi.resources.CustomResourceOptions;
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.getSubnets(GetSubnetsArgs.builder()
            .filters(GetSubnetsFilterArgs.builder()
                .name("vpc-id")
                .values(vpcId)
                .build())
            .build());

        var foo = new LaunchTemplate("foo", LaunchTemplateArgs.builder()
            .name("launch-template")
            .imageId("ami-516b9131")
            .instanceType("m1.small")
            .keyName("some-key")
            .build());

        var fooSpotFleetRequest = new SpotFleetRequest("fooSpotFleetRequest", SpotFleetRequestArgs.builder()
            .iamFleetRole("arn:aws:iam::12345678:role/spot-fleet")
            .spotPrice("0.005")
            .targetCapacity(2)
            .validUntil("2019-11-04T20:44:20Z")
            .launchTemplateConfigs(SpotFleetRequestLaunchTemplateConfigArgs.builder()
                .launchTemplateSpecification(SpotFleetRequestLaunchTemplateConfigLaunchTemplateSpecificationArgs.builder()
                    .id(foo.id())
                    .version(foo.latestVersion())
                    .build())
                .overrides(                
                    SpotFleetRequestLaunchTemplateConfigOverrideArgs.builder()
                        .subnetId(example.ids()[0])
                        .build(),
                    SpotFleetRequestLaunchTemplateConfigOverrideArgs.builder()
                        .subnetId(example.ids()[1])
                        .build(),
                    SpotFleetRequestLaunchTemplateConfigOverrideArgs.builder()
                        .subnetId(example.ids()[2])
                        .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(test_attach)
                .build());

    }
}
resources:
  foo:
    type: aws:ec2:LaunchTemplate
    properties:
      name: launch-template
      imageId: ami-516b9131
      instanceType: m1.small
      keyName: some-key
  fooSpotFleetRequest:
    type: aws:ec2:SpotFleetRequest
    name: foo
    properties:
      iamFleetRole: arn:aws:iam::12345678:role/spot-fleet
      spotPrice: '0.005'
      targetCapacity: 2
      validUntil: 2019-11-04T20:44:20Z
      launchTemplateConfigs:
        - launchTemplateSpecification:
            id: ${foo.id}
            version: ${foo.latestVersion}
          overrides:
            - subnetId: ${example.ids[0]}
            - subnetId: ${example.ids[1]}
            - subnetId: ${example.ids[2]}
    options:
      dependsOn:
        - ${["test-attach"]}
variables:
  example:
    fn::invoke:
      function: aws:ec2:getSubnets
      arguments:
        filters:
          - name: vpc-id
            values:
              - ${vpcId}

The overrides array within launchTemplateConfigs specifies a subnetId for each portion of capacity. The fleet distributes instances across these subnets, improving availability. This example queries subnets dynamically using getSubnets, then creates one override per subnet.

Beyond these examples

These snippets focus on specific Spot Fleet features: launch specifications and launch templates, allocation strategies and capacity distribution, and subnet overrides for multi-AZ placement. They’re intentionally minimal rather than full fleet deployments.

The examples rely on pre-existing infrastructure such as IAM fleet roles and instance profiles, VPC subnets and availability zones, and AMIs valid for the target region. They focus on fleet configuration rather than provisioning the surrounding infrastructure.

To keep things focused, common fleet patterns are omitted, including:

  • On-Demand capacity mixing (onDemandTargetCapacity)
  • Load balancer integration (loadBalancers, targetGroupArns)
  • Instance health replacement (replaceUnhealthyInstances)
  • Capacity rebalancing (spotMaintenanceStrategies)

These omissions are intentional: the goal is to illustrate how each fleet feature is wired, not provide drop-in capacity modules. See the Spot Fleet Request resource reference for all available configuration options.

Let's create AWS EC2 Spot Fleet Requests

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Deprecation & Alternatives
Should I use Spot Fleet Request for new deployments?
No. AWS strongly discourages use of the legacy APIs called by this resource. Use EC2 Fleet or Auto Scaling Group resources instead.
Launch Configuration
What's the difference between launch specifications and launch templates?
Both define how to launch instances, but they’re mutually exclusive. You must use either launchSpecifications or launchTemplateConfigs, not both. At least one is required. Launch templates are generally recommended for newer deployments.
Why am I getting errors with my launch specifications?
launchSpecifications takes similar but not identical inputs to aws.ec2.Instance. Check the AWS API reference for supported inputs, as there are limitations on what you can specify.
Why is my IAM instance profile not working in launch specifications?
Use iamInstanceProfileArn with the ARN from aws.iam.InstanceProfile, not the profile name. Launch specifications require the ARN attribute as input.
Networking & Multi-AZ Deployment
Why can't I specify multiple subnets in one launch configuration?
Multiple subnetId or availabilityZone parameters in the same launch configuration block are not supported. Use separate launch configuration blocks or launch template overrides, one per subnet.
How do I deploy my Spot Fleet across multiple availability zones?
Create separate launch configuration blocks (one per subnet) or use launch template overrides with different subnetId values, as shown in the multiple launch configurations example.
Capacity & Allocation
What allocation strategies are available for Spot Fleet?
Valid strategies are lowestPrice (default), diversified, capacityOptimized, capacityOptimizedPrioritized, and priceCapacityOptimized. This property is immutable after creation.
What does target capacity represent?
targetCapacity is the number of units to request. You can set capacity in terms of instances or performance characteristics like vCPUs, memory, or I/O.
Instance Lifecycle & Termination
What happens to my instances when the Spot Fleet request expires or is deleted?
Behavior depends on terminateInstancesWithExpiration (for expiration) and terminateInstancesOnDelete (for deletion). If terminateInstancesOnDelete isn’t specified, it defaults to the value of terminateInstancesWithExpiration.
What happens when a Spot instance is interrupted?
The instanceInterruptionBehaviour property controls this. Default is terminate, but you can set it to stop the instance instead. This property is immutable.
Does Spot Fleet automatically replace unhealthy instances?
No, by default replaceUnhealthyInstances is false. You must explicitly enable this if you want automatic replacement.
Fulfillment & Timeouts
How long does Pulumi wait for the Spot Fleet to be fulfilled?
If waitForFulfillment is set, Pulumi waits for the request to be fulfilled and throws an error if the 10-minute timeout is reached.
Immutability & Updates
What properties can't I change after creating a Spot Fleet?
Many properties are immutable: iamFleetRole, loadBalancers, targetGroupArns, allocationStrategy, context, fleetType, instanceInterruptionBehaviour, instancePoolsToUseCount, launchSpecifications, launchTemplateConfigs, onDemandAllocationStrategy, onDemandMaxTotalPrice, replaceUnhealthyInstances, spotPrice, targetCapacityUnitType, terminateInstancesWithExpiration, validFrom, and validUntil.

Using a different cloud?

Explore compute guides for other cloud providers: