EC2 Launch Templates Explained: Versions, Examples, and Auto Scaling
An EC2 launch template is a reusable, versioned blueprint for launching EC2 instances. It stores your instance settings (AMI, instance type, security groups, IAM role, user data) so you define them once and reference them every time, from a single manual launch to a fleet managed by an Auto Scaling Group.
EC2 launch templates explained
When you launch an EC2 instance, you specify a lot of parameters: which AMI to use, which instance type, which security groups, which key pair, what user data script to run, whether to encrypt the root volume. That is fine for one instance. For ten, it becomes error-prone. For a team where multiple people are launching instances, it becomes inconsistent.
A launch template solves this by saving all those parameters under a single name. When you, an Auto Scaling Group, or a CI/CD pipeline needs a new instance, it references the template instead of re-specifying everything from scratch.
Analogy
Think of a launch template like a recipe card for a server. The recipe says: use this OS image, this size machine, these firewall rules, run this setup script on first boot. Anyone can follow the recipe: a human in the console, the AWS CLI, or an Auto Scaling Group automatically replacing failed instances at 3am. The result is always the same server, built the same way.
Why launch templates matter
The problems launch templates solve are not obvious until you hit them. Here is what happens without them:
- Drift. Two engineers launch “the same” instance. One enables detailed monitoring. One uses a different instance type. One forgets to enforce IMDSv2. After a few months, your fleet is inconsistent in ways that are hard to audit.
- Repetition. Every new instance launch requires the same parameters to be specified again. Mistakes happen: wrong AMI, wrong security group, unencrypted volume.
- No audit trail. Without a template, there is no record of what configuration was used to launch a given instance. With a versioned template, you can trace exactly which version was active at any point.
- Unsafe updates. Swapping an AMI or changing user data across a fleet without versioning means all-or-nothing. With templates, you create a new version and roll it out gradually using instance refresh.
For Auto Scaling Groups, launch templates are effectively required. They are how AWS knows what instance to create when scaling out.
How launch templates work
A few key behaviours to understand before using them:
- Templates store defaults, not requirements. Most fields are optional. You can create a minimal template with just an AMI ID and instance type, then supply everything else at launch time. Or you can lock down every setting.
- Values can be overridden at launch. When launching an instance or creating an ASG, you can override specific fields from the template (for example, a different subnet or instance type for a specific environment) while inheriting everything else.
- Versions are additive. Every update creates a new version. Old versions are never modified or deleted automatically. You can reference any version by number, or use the aliases
$Latestor$Default. - ASGs reference a template and a version. Changing the version in the ASG is how you roll out configuration updates to a running fleet.
What a launch template stores
A launch template can store any combination of these settings. None are mandatory. Include what you want to standardise and leave the rest to be supplied at launch time.
| Setting | Description |
|---|---|
| AMI ID | The OS image to boot from. See AMIs explained. |
| Instance type | CPU and RAM profile (e.g., t3.medium, m6i.large). See the instance types guide. |
| Key pair | SSH key pair name. Consider using Session Manager to avoid storing key pairs entirely. |
| Security groups | Firewall rules controlling inbound and outbound traffic on the instance. |
| Subnet / Network interface | Which VPC and subnet to launch into. Often left out of the template and specified at launch time. |
| IAM instance profile | The IAM role the instance assumes on boot, granting it access to AWS services. |
| User data | Bootstrap script to run on first boot. See user data scripts. |
| EBS volume configuration | Root volume size, type (gp3), and whether to encrypt. Set Encrypted: true as a baseline default. |
| Spot request settings | Max price, interruption behaviour (stop/terminate/hibernate). |
| Instance metadata options | IMDSv1 vs IMDSv2, hop limit. Set HttpTokens: required to enforce IMDSv2. |
| Monitoring | Enable detailed CloudWatch monitoring (1-minute granularity instead of 5-minute). |
| Tags | Tags applied automatically to the launched instance, volumes, and network interfaces. |
When to use a launch template
Launch templates are useful any time you want consistent, repeatable EC2 instance launches:
- Auto Scaling Groups. Required. An ASG needs a launch template (or the legacy launch configuration) to know what instances to create when scaling out.
- Standardising team launches. If multiple people regularly launch EC2 instances, a template enforces consistent AMIs, security groups, and security settings without relying on documentation or tribal knowledge.
- Rolling out a new AMI safely. Create a new template version with the updated AMI, then use instance refresh to gradually replace instances in an ASG while keeping a minimum percentage healthy.
- Mixed Spot and on-demand fleets. Launch templates are required for mixed instance type policies in ASGs. Launch configurations cannot do this.
- Enforcing security baselines. Bake IMDSv2 enforcement, encrypted root volumes, and an IAM instance profile into the template so every instance is compliant by default, without relying on anyone to remember the settings.
- Scripted or pipeline-driven launches. Any automated process that launches EC2 instances benefits from a template: fewer parameters to pass, less surface area for mistakes.
Launch template vs launch configuration
If you are working with existing AWS infrastructure, you may encounter launch configurations, the older predecessor to launch templates. Here is how they compare:
| Feature | Launch template | Launch configuration |
|---|---|---|
| Versioning | Yes: unlimited versions, with rollback | No: immutable once created |
| Updates | Create a new version; old version stays intact | Must create an entirely new launch configuration |
| IMDSv2 support | Yes | No |
| Mixed Spot / on-demand ASGs | Yes | No |
| T2/T3 Unlimited mode | Yes | No |
| Use outside of Auto Scaling | Yes: also works for individual instance launches | No: ASG use only |
| Actively developed by AWS | Yes | No: feature frozen |
| Recommended for new work | Yes | No |
AWS has stated that launch configurations will not receive new EC2 feature support. If you have existing ASGs using launch configurations, migrating to launch templates is worth prioritising, especially if you want Spot support, IMDSv2 enforcement, or instance refresh. New work should always start with a launch template.
Launch template vs launching EC2 manually
If you are launching your first EC2 instance, doing it manually through the console is completely reasonable. The trade-offs become clear once you do it more than a few times:
| Manual launch | Launch template | |
|---|---|---|
| Setup time | Specify all parameters each time | Specify once, reuse indefinitely |
| Consistency | Depends on who launches it | Same settings every time |
| Auto Scaling | Not possible | Required for ASGs |
| Audit trail | None | Version history in AWS |
| Rollback | Recreate manually | Switch to a previous version number |
| Best for | One-off experiments, learning | Any repeated or automated launch |
Creating a launch template
In the console: go to EC2 → Launch Templates → Create launch template. Fill in the name, then configure settings the same way you would when launching an instance directly: AMI, instance type, key pair, security groups, storage, user data. Every field has a UI.
Via the CLI: pass all settings as a JSON object in the —launch-template-data flag. This example creates a production-ready web server template with encrypted storage and IMDSv2 enforced:
aws ec2 create-launch-template \
--launch-template-name web-server-template \
--version-description "Initial version" \
--launch-template-data '{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "t3.medium",
"KeyName": "my-key-pair",
"SecurityGroupIds": ["sg-0abc12345def67890"],
"IamInstanceProfile": {
"Name": "WebServerInstanceProfile"
},
"UserData": "IyEvYmluL2Jhc2gKZG5mIGluc3RhbGwgLXkgbmdpbngKc3lzdGVtY3RsIGVuYWJsZSBuZ2lueApzeXN0ZW1jdGwgc3RhcnQgbmdpbng=",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 30,
"VolumeType": "gp3",
"DeleteOnTermination": true,
"Encrypted": true
}
}
],
"MetadataOptions": {
"HttpTokens": "required",
"HttpPutResponseHopLimit": 1
},
"TagSpecifications": [
{
"ResourceType": "instance",
"Tags": [
{"Key": "Role", "Value": "web-server"},
{"Key": "Environment", "Value": "production"}
]
}
]
}'The UserData field must be base64-encoded. The string above decodes to a script that installs and starts Nginx. Use —cli-binary-format raw-in-base64-out to pass plain text and have the CLI encode it automatically, or pre-encode your user data script before inserting it here.
Two settings in the template above are non-negotiable for production. HttpTokens: required enforces IMDSv2, blocking SSRF attacks from retrieving IAM credentials via the metadata endpoint. Encrypted: true on the EBS volume encrypts the root disk at rest. Both are free, have no performance trade-off on gp3, and should be in every launch template you create.
Versioning launch templates
Every time you update a launch template, you create a new version. The old version is untouched. You can have as many versions as you need, each independently referenceable, and none are deleted automatically.
Analogy
Think of launch template versions like Git commits. Each commit is immutable and numbered. You can reference any past commit by its hash (version number). You do not delete old commits when you make new ones. And “default version” is like your main branch HEAD: it points to whatever you last promoted, not necessarily the newest commit. When something goes wrong, you just move HEAD back.
To create a new version with an updated AMI, specify only what changed. All other settings are inherited from the source version:
aws ec2 create-launch-template-version \
--launch-template-name web-server-template \
--source-version 1 \
--version-description "Updated to Amazon Linux 2023 April patch" \
--launch-template-data '{
"ImageId": "ami-0newami1234567890"
}'Mark the new version as the default:
aws ec2 modify-launch-template \
--launch-template-name web-server-template \
--default-version 2View all versions and their status:
aws ec2 describe-launch-template-versions \
--launch-template-name web-server-template \
--query "LaunchTemplateVersions[*].[VersionNumber,VersionDescription,DefaultVersion]" \
--output tableTo roll back after a bad deployment, set —default-version back to the previous version number and trigger another instance refresh. New instances will pick up the old configuration immediately.
Choosing a version: $Latest vs $Default vs pinned
When you reference a launch template (in an ASG, a CLI command, or infrastructure-as-code) you must specify which version to use. There are three options:
| Version reference | What it means | When to use it |
|---|---|---|
$Latest | Resolves to the most recently created version at launch time | Development and staging environments where you want new instances to always reflect your latest changes without updating the ASG separately |
$Default | Resolves to whichever version is currently marked as the default | Production environments. You control rollouts by changing the default version. The ASG itself does not need to be updated. |
Specific version (e.g., 3) | Always uses that exact version number, regardless of what the default is | Pinning a resource to a known-good version, canary deployments, or compliance requirements where the configuration must be immutable |
Use $Default for production Auto Scaling Groups. It separates creating a new template version (which anyone can do) from promoting it to production (which requires you to explicitly update the default). This is a lightweight but effective change gate that prevents accidental rollouts.
Using launch templates with Auto Scaling Groups
An Auto Scaling Group uses the launch template to know what instances to create when scaling out. You specify the template name and version when creating or updating the ASG.
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name web-asg \
--launch-template "LaunchTemplateName=web-server-template,Version=\$Default" \
--min-size 2 \
--max-size 10 \
--desired-capacity 2 \
--vpc-zone-identifier "subnet-abc,subnet-def"Real-world scenario: rolling out a patched AMI. Your security team has released a new AMI and you need to roll it out across 20 production instances without downtime. Here is the process:
- Create a new launch template version with the patched AMI (inheriting all other settings from version 1).
- Mark the new version as the default.
- Trigger an instance refresh on the ASG. AWS will gradually replace instances while keeping at least 90% healthy throughout.
# Step 1: new template version with updated AMI only
aws ec2 create-launch-template-version \
--launch-template-name web-server-template \
--source-version 1 \
--version-description "Patched AMI April 2026" \
--launch-template-data '{"ImageId": "ami-0patchedami1234567"}'
# Step 2: promote it to default
aws ec2 modify-launch-template \
--launch-template-name web-server-template \
--default-version 2
# Step 3: rolling replacement — keeps 90% of instances healthy at all times
aws autoscaling start-instance-refresh \
--auto-scaling-group-name web-asg \
--preferences '{"MinHealthyPercentage": 90, "InstanceWarmup": 60}'AWS gradually terminates old instances and launches new ones using the updated template, maintaining capacity throughout. You can monitor progress in the EC2 console. If something goes wrong, cancel the refresh and roll the default version back to version 1. The ASG will revert on its next scaling event.
Mixed instance types and Spot
Launch templates are required for mixed instance type policies: the ability to run an ASG across multiple instance families and mix Spot instances with on-demand in the same group. This is not possible with launch configurations.
The example below creates an ASG that runs 20% on-demand (stable, always available base) and 80% Spot (cheaper, interruptible). Three instance types are listed so AWS can pick from more capacity pools. This reduces the risk of all Spot capacity being unavailable at once:
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name mixed-asg \
--mixed-instances-policy '{
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateName": "web-server-template",
"Version": "$Default"
},
"Overrides": [
{"InstanceType": "t3.medium"},
{"InstanceType": "t3a.medium"},
{"InstanceType": "t3.large"}
]
},
"InstancesDistribution": {
"OnDemandPercentageAboveBaseCapacity": 20,
"SpotAllocationStrategy": "capacity-optimized"
}
}' \
--min-size 2 \
--max-size 10 \
--desired-capacity 4 \
--vpc-zone-identifier "subnet-abc,subnet-def"Use capacity-optimized as your Spot allocation strategy. It directs AWS to launch from pools with the most available capacity, which also happen to have the lowest interruption rates. Listing three or more instance types in the overrides gives AWS enough flexibility to find available capacity even during peak demand. See the Spot instances guide for detail on interruption handling.
Common mistakes
Most launch template mistakes either expose a security gap (unencrypted volumes, IMDSv1) or cause a surprise rollout to production ($Latest in an ASG). Both categories are easy to avoid by building the right defaults into your template from the start.
Using launch configurations for new work. Launch configurations are feature-frozen. They cannot use IMDSv2, cannot support mixed Spot/on-demand fleets, and must be replaced entirely for any change. Always use launch templates for new ASGs. If you have existing launch configurations, migrate them. The process is straightforward and unlocks features you cannot get otherwise.
Hardcoding AMI IDs without a management strategy. An AMI ID is a snapshot in time. When AWS releases a new Amazon Linux 2023 patch or you build an updated golden AMI, you need to create a new template version. Use AWS Systems Manager Parameter Store to store the current AMI ID as a parameter, then reference it in your template. AMI updates then flow through one place instead of requiring manual template edits.
Not enforcing IMDSv2. Always include
“MetadataOptions”: {“HttpTokens”: “required”}in every launch template. Without this, the metadata endpoint is accessible via IMDSv1, which is vulnerable to SSRF attacks that can retrieve IAM credentials assigned to the instance. There is no valid reason to leave this out on a new template.Leaving root volumes unencrypted. Include
“Encrypted”: truein the EBS block device mapping. Unencrypted root volumes expose OS and application data to anyone with access to the underlying EBS snapshot. Encryption on gp3 is free and has no performance trade-off.Using $Latest in production Auto Scaling Groups. With
$Latest, any new template version (including a work-in-progress one) immediately affects what instances the ASG launches next. Use$Defaultin production so you explicitly control when a new version goes live. Reserve$Latestfor development environments where iteration speed matters more than stability.
Summary
- A launch template is a named, versioned set of EC2 instance launch parameters: AMI, instance type, security groups, IAM role, user data, and more.
- They replace the older, immutable launch configurations, which are feature-frozen and do not support IMDSv2 or mixed Spot/on-demand fleets.
- Every update creates a new version. Old versions are never deleted. You can roll back at any time by switching which version is the default.
- Auto Scaling Groups reference a template and version. Use
$Defaultin production and$Latestin dev and staging. - Use instance refresh to roll a new AMI version out to an ASG gradually, keeping a minimum percentage of instances healthy throughout.
- Always set
HttpTokens: required(IMDSv2) andEncrypted: trueon the root volume in every launch template.
Frequently asked questions
What is the difference between a launch template and a launch configuration?
Launch configurations are the older, legacy method for configuring Auto Scaling Groups. They are immutable: you cannot modify them after creation. Launch templates replace them entirely: they support versioning, can be updated incrementally, support newer EC2 features like IMDSv2 and mixed Spot/on-demand fleets, and can be used outside of Auto Scaling. AWS has stopped adding new EC2 features to launch configurations. Use launch templates for all new work.
Can I use a launch template without Auto Scaling?
Yes. Launch templates work anywhere you launch EC2 instances: from the console, the CLI (aws ec2 run-instances --launch-template), and via the API. Auto Scaling Groups are just the most common use case. You can also use them to ensure consistent, auditable instance launches without each person specifying parameters manually.
Should I use $Latest or $Default in my Auto Scaling Group?
For production Auto Scaling Groups, use $Default. This gives you an explicit control point: you decide exactly when new instances pick up a new configuration by changing which version is marked as default. $Latest is convenient in development where you want instances to always reflect your latest changes, but it can cause unintended rollouts in production if someone creates a new template version without realising the ASG will immediately start using it.
Can I update a launch template without replacing the old version?
Yes. Creating a new version does not touch existing versions. Old versions remain available and can be referenced by version number. This is one of the main advantages over launch configurations, which had to be replaced entirely. You can roll back to any previous version at any time by updating the ASG or launching instances with a specific version number.
What settings belong in a launch template vs at launch time?
Put settings that should be standardised into the template: AMI ID, instance type, IAM role, security groups, EBS encryption, IMDSv2 enforcement, and user data. Override at launch time what varies per environment: subnet, specific tags, instance type for one-off tests. An ASG can also override the instance type from the template to support mixed instance policies.