Tagging EC2 Resources
A tag is a simple label you attach to an AWS resource: a key and a value, like Environment = production. Tags do not change how a resource behaves, but they let you find, group, bill, and secure your resources at scale. Once you run more than a handful of EC2 (Elastic Compute Cloud, AWS’s virtual server service) instances, tags become the difference between a tidy account and total chaos. This page shows how to tag instances, volumes, and snapshots, and the gotchas that quietly leave resources untagged.
What tags are and why they matter
A tag is key-value metadata you attach to a resource. The key is the category (for example Owner), and the value is the detail (for example data-team). Each resource can have up to 50 tags. Keys can be up to 128 characters and values up to 256 characters.
Tags power four big jobs:
| Use case | What tags give you |
|---|---|
| Organization | Filter the console and CLI to “just the prod web servers” instead of scrolling through everything. |
| Cost allocation | See exactly how much each team, project, or environment spends in your bill. |
| Automation | Scripts and tools (backups, auto-stop schedules) act only on resources with a matching tag. |
| Access control (tag-based IAM) | Write IAM (Identity and Access Management) policies that allow actions only on resources carrying a specific tag. |
When to use this: always. Tag every resource you create. There is no cost for tags themselves, and untagged resources are the ones nobody can explain six months later. When NOT to: do not put secrets (passwords, tokens) in tags. Tags are visible to anyone with read access and appear in logs.
A tagging standard worth copying
Tags only help if they are consistent. env, Env, and environment are three different keys to AWS. Agree on a small standard and enforce it. A solid starting set:
| Tag key | Example value | Purpose |
|---|---|---|
Environment | production | Separate prod, staging, dev. |
Owner | data-team | Who to contact and who pays attention. |
Project | checkout-api | Group resources by the app they serve. |
CostCenter | cc-4210 | Maps spend to a finance code. |
Tip: Pick one casing convention (Title Case keys are common) and one delimiter for values, then stop debating it. Consistency matters far more than which style you choose.
Tagging at launch
The cleanest moment to tag is when you create the resource, so nothing is ever untagged.
Console steps:
- Open the EC2 console and choose Launch instances.
- Configure the AMI (Amazon Machine Image, the template for the disk), instance type, and key pair as usual.
- Expand Advanced details, or scroll to the Tags panel.
- Choose Add tag, enter a key and value (for example
Environment/production). - Under Resource types, tick Instances, Volumes, and Network interfaces so the same tag flows onto the disk too.
- Repeat for each tag in your standard, then Launch instance.
CLI equivalent (AWS CLI v2). The --tag-specifications flag tags the instance and its EBS (Elastic Block Store, persistent disk) volume in one call:
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key \
--tag-specifications \
'ResourceType=instance,Tags=[{Key=Environment,Value=production},{Key=Owner,Value=data-team},{Key=Project,Value=checkout-api},{Key=CostCenter,Value=cc-4210}]' \
'ResourceType=volume,Tags=[{Key=Environment,Value=production},{Key=Project,Value=checkout-api}]'
Output:
{
"Instances": [
{
"InstanceId": "i-0a1b2c3d4e5f",
"InstanceType": "t3.micro",
"State": { "Name": "pending" }
}
]
}
Tagging existing resources with create-tags
To add or change tags on resources that already exist, use create-tags. It works on instances, volumes, snapshots, security groups, and more. Setting a key that already exists overwrites its value.
Console steps:
- In the EC2 console, select the resource (for example an instance or a volume).
- Open the Tags tab.
- Choose Manage tags.
- Add tag, enter the key and value, then Save.
CLI equivalent:
aws ec2 create-tags \
--resources i-0a1b2c3d4e5f vol-0a1b2c3d \
--tags Key=Environment,Value=production Key=Owner,Value=data-team
This command prints nothing on success. To check the result, describe the tags:
aws ec2 describe-tags --filters "Name=resource-id,Values=i-0a1b2c3d4e5f"
Output:
{
"Tags": [
{ "Key": "Environment", "ResourceId": "i-0a1b2c3d4e5f", "ResourceType": "instance", "Value": "production" },
{ "Key": "Owner", "ResourceId": "i-0a1b2c3d4e5f", "ResourceType": "instance", "Value": "data-team" }
]
}
To remove a tag, use delete-tags:
aws ec2 delete-tags --resources i-0a1b2c3d4e5f --tags Key=Owner
Defining tags in infrastructure as code
If you create resources with Terraform or CloudFormation, define tags in the template so they are never forgotten.
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Environment = "production"
Owner = "data-team"
Project = "checkout-api"
CostCenter = "cc-4210"
}
}
Gotcha: cost reports are not retroactive
Adding a CostCenter tag does not automatically split it out in your bill. You must turn each tag into a cost allocation tag first:
- Open the Billing and Cost Management console (as the management account).
- Go to Cost allocation tags.
- Select your tag keys (for example
CostCenter,Project). - Choose Activate.
Warning: Activation is not retroactive. Tagged spend only appears in Cost Explorer and the Cost and Usage Report from the day you activate the tag onward, and data can take up to 24 hours to show. Activate your standard tags on day one, before the spend you care about happens.
Gotcha: ASG and CloudFormation resources can go untagged
Tags do not automatically flow from a parent to the things it creates:
- Auto Scaling Groups (ASG): an ASG launches instances from a launch template. Tags on the ASG only reach those instances if you set Tag new instances (the
PropagateAtLaunchflag). Tags inside the launch template itself cover the instance and volume directly, which is the more reliable approach. - CloudFormation: CloudFormation automatically applies stack-level tags to resources that support them, but volumes created from an instance’s block device mappings and some nested resources may still need tags declared explicitly in the template.
The result is the classic mystery: an instance is tagged but its 500 GB volume is not, so a big chunk of storage spend lands in the “untagged” bucket.
Best practices
- Tag at creation time (launch template,
run-instances, or IaC), so resources are never born untagged. - Tag the volume and network interface too, not just the instance, or your storage spend goes unattributed.
- Agree on a small, fixed key list and one casing convention; enforce it with AWS Config rules or tag policies.
- Activate cost allocation tags in Billing on day one, since the data is not backfilled.
- Set
PropagateAtLaunchon ASG tags, and prefer tagging inside the launch template. - Never store secrets in tags; they are visible to any reader and appear in CloudTrail logs.
- Periodically audit for untagged resources with
describe-instancesfiltered on missing keys, and remediate.