A RunInstances call can take dozens of parameters: AMI, instance type, key pair, security groups, subnet, IAM profile, block devices, user data, tags. Repeating that everywhere is error-prone and impossible to version.
A launch template captures all of it as a single, versioned object. You define the configuration once, then launch from it with a two-field call - and the same template is what Auto Scaling groups and Spot fleets consume. This page shows how to create, version, and launch from templates.
CreateLaunchTemplate registers version 1 of a template. The configuration lives under LaunchTemplateData, which mirrors the RunInstances parameter shape.
That single call creates the template with version number 1. Every field is optional except that a usable launch needs at least an AMI and an instance type, supplied either here or at launch time.
Once a template exists, launching is a two-field RunInstances call. You reference the template by name or id and pick a version, then override only what differs for this launch.
# --- Python (boto3) ---import boto3ec2 = boto3.client("ec2", region_name="us-east-1")resp = ec2.run_instances( LaunchTemplate={"LaunchTemplateName": "web-app", "Version": "$Latest"}, MinCount=1, MaxCount=2, # Override just for this launch; template supplies the rest. TagSpecifications=[{ "ResourceType": "instance", "Tags": [{"Key": "Name", "Value": "web"}], }],)ids = [i["InstanceId"] for i in resp["Instances"]]print(ids)
Any parameter you pass directly to RunInstances overrides the template's value for that launch only. This is the pattern: pin the stable configuration in the template, override the per-launch specifics inline.
Launch template versions are immutable and append-only. You never edit version 1; you create version 2 with CreateLaunchTemplateVersion, optionally seeding it from an existing version so you only specify what changed.
Because old versions never change, a rollback is just "launch from version 1 again". This is the core reason launch templates beat the older launch configurations, which were entirely immutable objects you had to recreate wholesale.
When you launch, Version accepts a specific number ("2") or one of two aliases. $Latest always resolves to the highest version number. $Default resolves to whichever version you designated as default with ModifyLaunchTemplate.
The distinction matters for Auto Scaling. Pointing an ASG at $Latest means every new version instantly affects new instances - convenient but risky. Pointing at $Default lets you stage a new version, test it, then promote it to default when ready, giving you a controlled rollout.
# --- Python (boto3) ---import boto3ec2 = boto3.client("ec2", region_name="us-east-1")# Promote version 2 to the default once it is validated.ec2.modify_launch_template( LaunchTemplateName="web-app", DefaultVersion="2",)
// --- TypeScript (AWS SDK v3) ---import { EC2Client, ModifyLaunchTemplateCommand } from "@aws-sdk/client-ec2";const ec2 = new EC2Client({ region: "us-east-1" });// Promote version 2 to the default once it is validated.await ec2.send(new ModifyLaunchTemplateCommand({ LaunchTemplateName: "web-app", DefaultVersion: "2",}));
LaunchTemplateData accepts nearly everything RunInstances does: ImageId, InstanceType, KeyName, SecurityGroupIds, IamInstanceProfile, BlockDeviceMappings, UserData (base64-encoded), TagSpecifications, MetadataOptions (to enforce IMDSv2), and InstanceMarketOptions (to request Spot). Putting IMDSv2 enforcement and Spot options in the template means every consumer - your direct launches, ASGs, and fleets - inherits them consistently.
Trying to edit a version. Versions are immutable. Create a new version with CreateLaunchTemplateVersion; do not expect to mutate an existing one.
Assuming $Latest is the default. The newest version is not automatically the default. Set the default explicitly with ModifyLaunchTemplate.
Un-encoded user data.UserData in a launch template must be base64-encoded, unlike some higher-level helpers that encode for you.
ASG pinned to $Latest in production. New versions take effect immediately with no staging. Prefer $Default and promote deliberately.
Duplicate template names.LaunchTemplateName must be unique per region; a second CreateLaunchTemplate with the same name fails.
Overrides you forgot are overrides. A parameter passed to RunInstances silently wins over the template; if a template value seems ignored, check for an inline override.
Inline RunInstances parameters work for one-off launches, but repeat configuration and cannot be versioned or shared with ASGs and fleets.
Launch configurations are the legacy Auto Scaling primitive; they are immutable and are being phased out in favor of launch templates - do not choose them for new work.
IaC (CloudFormation, CDK, Terraform) can declare the launch template itself, which is the right home for the template definition while the SDK handles runtime launches.
Use a launch template whenever the same configuration is launched more than once or is consumed by an ASG or Spot fleet.
A versioned object that captures instance launch configuration - AMI, type, key, security groups, user data, and more - so you can launch repeatedly without repeating parameters.
How do I launch an instance from a template?
Pass LaunchTemplate (name or id plus a version) to RunInstances, along with MinCount/MaxCount. Override any per-launch specifics inline.
Can I edit a launch template version?
No. Versions are immutable. Create a new version with CreateLaunchTemplateVersion, optionally copying from an existing one via SourceVersion.
What is the difference between $Latest and $Default?
$Latest is always the highest version number. $Default is whichever version you designated as default. Use $Default for staged rollouts you control.
How do I set the default version?
Call ModifyLaunchTemplate with DefaultVersion set to the version number you want as the new default.
Do launch templates replace launch configurations?
Yes. Launch configurations are the legacy Auto Scaling primitive and are being retired. Use launch templates for all new work; they are versioned and far more capable.
How do I put user data in a template?
Set UserData in LaunchTemplateData as a base64-encoded string. Unlike some helpers, the template does not encode it for you.
Can I enforce IMDSv2 through a template?
Yes. Set MetadataOptions.HttpTokens to required in LaunchTemplateData, and every instance launched from the template requires IMDSv2 tokens.
Do overrides at launch change the template?
No. Parameters passed to RunInstances apply only to that launch. The template is unchanged; the override is per-call.
Can Auto Scaling groups use launch templates?
Yes, and it is the recommended approach. An ASG references a launch template and version, and Spot fleets do the same, making the template the shared provisioning primitive.