Launch configurations are the legacy mechanism for defining the template that Amazon EC2 Auto Scaling groups use to launch new instances. In Terraform, the aws_launch_configuration resource maps directly to the AWS API for launch configurations, and while AWS now actively discourages their use in favor of launch templates, many existing production stacks still rely on them. This article covers the resource in full depth from the reference documentation, including immutable behavior, lifecycle management with create_before_destroy, spot pricing, block device handling, import workflows, and the recommended migration path to aws_launch_template.
Introduction
Terraform providers expose AWS launch configurations as a declarative resource that couples an AMI, instance type, security settings, and optional launch parameters into a single named entity that an Auto Scaling group can reference. The resource is documented as providing a resource to create a new launch configuration, used for autoscaling groups. Because the underlying AWS API makes launch configurations immutable after creation, Terraform must destroy and recreate the resource on any change. That immutability drives the core operational pattern for Terraform users: use name_prefix instead of a static name, pair it with a lifecycle { create_before_destroy = true } block, and reference the configuration name in aws_autoscaling_group. The documentation explicitly warns that the use of launch configurations is discouraged in favor of launch templates, with a note in the AWS EC2 Documentation.
Resource Overview and Core Behavior
The AWS API treats a launch configuration as immutable. Launch Configurations cannot be updated after creation with the Amazon Web Service API. In order to update a Launch Configuration, Terraform will destroy the existing resource and create a replacement. In order to effectively use a Launch Configuration resource with an AutoScaling Group resource, it’s recommended to specify createbeforedestroy in a lifecycle block.
This behavior means any change to attributes such as image_id, instance_type, spot_price, or block device mappings triggers a destroy-create cycle. Without create_before_destroy, an Auto Scaling group would temporarily lose its launch configuration reference during the update window.
The recommended naming pattern avoids hard-coded names that would collide on replacement:
Either omit the Launch Configuration name attribute, or specify a partial name with name_prefix.
When using aws_launch_configuration with aws_autoscaling_group, it is recommended to use the name_prefix Optional instead of the name Optional attribute. This will allow Terraform lifecycles to detect changes to the launch configuration and update the autoscaling group correctly.
Required and Optional Arguments
The following arguments are required:
image_id- The EC2 image ID to launch.instance_type- The size of instance to launch.
The following arguments are optional:
region- Optional Region where this resource will be managed. Defaults to the Region set in the provider configuration.associate_public_ip_address- Optional Associate a public ip address with an instance in a VPC.ebs_block_device- Optional Additional EBS block devices to attach to the instance. See Block Devices below for details.ebs_optimized- Optional If true, the launched EC2 instance will be EBS-optimized.enable_monitoring- Optional Enables/disables detailed monitoring.
Additional optional arguments documented in the provider include name, name_prefix, spot_price, key_name, security_groups, iam_instance_profile, user_data, ebs_optimized, and more. Spot pricing is a notable parameter for cost optimization.
Launch configurations can set the spot instance pricing to be used for the Auto Scaling Group to reserve instances. Simply specifying the spot_price parameter will set the price on the Launch Configuration which will attempt to reserve your instances at this price.
Example Usage Patterns
A minimal launch configuration using an AMI data source:
```hcl
data "awsami" "ubuntu" {
mostrecent = true
filter {
name = "name"
values = ["ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["paravirtual"]
}
owners = ["099720109477"] # Canonical
}
resource "awslaunchconfiguration" "asconf" {
name = "webconfig"
imageid = data.awsami.ubuntu.id
instance_type = "t1.micro"
}
```
The same pattern with name_prefix and lifecycle for safe updates:
```hcl
data "awsami" "ubuntu" {
mostrecent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "awslaunchconfiguration" "asconf" {
nameprefix = "terraform-lc-example-"
imageid = data.awsami.ubuntu.id
instancetype = "t2.micro"
lifecycle {
createbefore_destroy = true
}
}
resource "awsautoscalinggroup" "bar" {
name = "terraform-asg-example"
launchconfiguration = awslaunchconfiguration.asconf.name
minsize = 1
maxsize = 2
lifecycle {
createbeforedestroy = true
}
}
```
With this setup Terraform generates a unique name for your Launch Configuration and can then update the AutoScaling Group without conflict before destroying the previous Launch Configuration.
Spot pricing example:
```hcl
data "awsami" "ubuntu" {
mostrecent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "awslaunchconfiguration" "asconf" {
imageid = data.awsami.ubuntu.id
instancetype = "m4.large"
spotprice = "0.001"
lifecycle {
createbefore_destroy = true
}
}
resource "awsautoscalinggroup" "bar" {
name = "terraform-asg-example"
launchconfiguration = awslaunchconfiguration.asconf.name
}
```
Attributes Reference and Import
Attributes Reference exported by the resource:
id- The ID of the launch configuration.
Import support is name based:
Launch configurations can be imported using the name, e.g.
$ terraform import aws_launch_configuration.as_conf terraform-lg-123456
In Terraform v1.5.0 and later, use an import block to import launch configurations using the name. For example:
hcl
import {
to = aws_launch_configuration.example
identity = {
name = "example"
}
}
Using terraform import, import launch configurations using the name. For example:
% terraform import aws_launch_configuration.example example
Attribute metadata also includes:
name- String name of the launch configuration.account_id- String AWS Account where this resource is managed.region- String Region where this resource is managed.
Block Device Considerations
AWS publishes a list of which ephemeral devices are available on each type. The devices are always identified by the virtual_name in the format "ephemeral{0..N}".
Terraform provides a note on block device changes:
~> NOTE: Changes to *blockdevice configuration of existing resources cannot currently be detected by Terraform. After updating to block device configuration, resource recreation can be manually triggered by using the taint command.
This limitation is important when using ebs_block_device or ephemeral device mappings. Because Terraform cannot detect drift, manual recreation may be required.
Launch Configuration Spec Summary
| Attribute | Type | Required | Description |
|---|---|---|---|
| image_id | string | Yes | The EC2 image ID to launch |
| instance_type | string | Yes | The size of instance to launch |
| name | string | No | name of the launch configuration |
| name_prefix | string | No | Prefix for generated name |
| spot_price | string | No | Max price for Spot instances |
| ebs_optimized | bool | No | If true, launched EC2 instance will be EBS-optimized |
| enable_monitoring | bool | No | Enables/disables detailed monitoring |
| associatepublicip_address | bool | No | Associate a public IP in VPC |
| ebsblockdevice | block | No | Additional EBS block devices |
Launch Templates as the Preferred Alternative
AWS and Terraform now recommend launch templates over launch configurations. The provider documentation includes the warning:
!> WARNING: The use of launch configurations is discouraged in favor of launch templates. Read more in the AWS EC2 Documentation.
Launch templates offer versioning, support for more instance types, and richer metadata. A production-ready launch template in Terraform typically includes:
- AMI lookup with most recent filter
- Instance type
- Security groups
- IAM instance profile
- Base64 encoded user data
- Tag specifications for instances and volumes
- Lifecycle
create_before_destroywithname_prefix
Example from production guidance:
```hcl
data "awsami" "al2023" {
mostrecent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "awslaunchtemplate" "app" {
nameprefix = "app-"
description = "Launch template for application servers"
imageid = data.awsami.al2023.id
instancetype = "t3.medium"
lifecycle {
createbeforedestroy = true
}
vpcsecuritygroupids = [
awssecuritygroup.app.id,
awssecuritygroup.monitoring.id,
]
iaminstanceprofile {
name = awsiaminstanceprofile.app.name
}
userdata = base64encode(templatefile("${path.module}/scripts/bootstrap.sh", {
environment = var.environment
appversion = var.appversion
}))
tagspecifications {
resourcetype = "instance"
tags = {
Name = "app-server"
Environment = var.environment
}
}
tagspecifications {
resource_type = "volume"
tags = {
Name = "app-server-volume"
Environment = var.environment
}
}
}
```
This pattern mirrors launch configuration essentials while adding template versioning and safer updates.
Comparison: Launch Configuration vs Launch Template
| Feature | Launch Configuration | Launch Template |
|---|---|---|
| Immutability | Immutable after creation | Versioned, mutable |
| AWS Recommendation | Discouraged | Recommended |
| Spot support | spot_price parameter | Multiple pricing options |
| User data | Supported | Supported, base64 required |
| Tagging | Limited | tag_specifications for instance/volume |
| Name handling | name / name_prefix | name_prefix recommended |
Best Practices for Existing Launch Configurations
When you must maintain launch configurations:
- Always use
name_prefixinstead of a fixednameto allow Terraform to generate unique names on replacement. - Set
lifecycle { create_before_destroy = true }on both the launch configuration and the autoscaling group. - Reference the launch configuration by
aws_launch_configuration.as_conf.namein the ASG. - Pin AMI lookups with filters and
most_recent = truefor repeatable builds. - Avoid changes to
ebs_block_devicewithout planning a manual taint, as Terraform cannot detect drift. - Plan migration to
aws_launch_templatewithaws_autoscaling_groupusinglaunch_template { id = ... version = "$Latest" }.
Conclusion
The aws_launch_configuration resource remains a functional bridge for teams with legacy Auto Scaling groups, but its immutable nature imposes operational constraints that require careful lifecycle management. The combination of name_prefix and create_before_destroy is essential to avoid service interruption during updates, and spot pricing can be injected via spot_price for cost-sensitive workloads. Attribute support covers the required image_id and instance_type, with optional controls for EBS optimization, monitoring, public IP association, and block devices, though block device drift remains undetectable by Terraform.
Import workflows are straightforward using the launch configuration name, with both legacy terraform import commands and v1.5+ import blocks supported. Given the explicit provider warning that the use of launch configurations is discouraged in favor of launch templates, new designs should adopt aws_launch_template for versioning, richer tagging, and future-proof compatibility, while existing launch configurations should be maintained with the safe naming and lifecycle patterns described here until migration is feasible.