Well-Architected Framework
Create and implement a cloud resource tagging strategy
Managing thousands of cloud resources across regions, environments, and teams is complex. Tags are key-value pairs that help you organize, identify, and filter resources. A clear tagging strategy becomes essential as your resource count grows.
A tagging strategy gives every cloud resource a consistent set of metadata that links it to a team, environment, and cost center. Without tags, cost allocation is opaque, compliance audits are error-prone, and automation policies cannot reliably identify their targets.
AWS, Azure, and IBM maintain best practices and strategies for tagging your cloud resources. Follow these best practices when creating your tagging strategy. You can apply these concepts to other infrastructure providers.
You can implement your tagging strategy using infrastructure as code (IaC) and enforce compliance with policy as code to prevent deploying resources that don't meet your tagging requirements.
Why implement a tagging strategy
A cloud resource tagging strategy addresses the following operational challenges:
Track spending by team: Without granular tagging, cost allocation reports group resources at the account level, making it hard to attribute spending to a specific team, project, or application. Tags like CostCenter and Application let you break down cloud bills by the groups that generate them, so you can hold teams accountable and make informed budget decisions.
Prevent compliance gaps: Untagged resources bypass governance policies and create blind spots in security and audit reporting. When regulators or internal auditors ask which resources store customer data or belong to a regulated workload, untagged infrastructure has no reliable answer. Enforcing required tags at deploy time ensures every resource carries the metadata your compliance processes depend on.
Automate resource management: Tags let automation act on resources directly. For example, a lifecycle policy can shut down all instances tagged Environment: dev outside business hours. A cleanup job can delete any resource tagged Temporary: true after 30 days. Without consistent tags, these automations cannot reliably identify their targets.
How to deploy tags using infrastructure as code
Consistent implementation of your tagging strategy helps you track infrastructure costs, manage resources, and ensure compliance. Manual tagging leads to resources with incorrect or missing tags.
When you manage your infrastructure with Terraform, you can define tags within your configuration. Terraform applies these tags to all resources it creates.
The following creates an AWS EC2 instance and adds several tags to the resource:
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server-prod"
Environment = "production"
Owner = "platform-team"
CostCenter = "engineering"
Application = "website"
}
}
The tags attach to every AWS EC2 instance that Terraform creates from this resource block. Tags like Environment and CostCenter let you filter resources in the AWS console, build cost allocation reports, and scope automation policies to specific groups of instances.
The AWS and Google Cloud Platform (GCP) Terraform providers let you add default tags to all resources they create. Default tags enforce a consistent tagging strategy across all resources Terraform manages. Every resource gets the minimum required tags, but you can override them per resource. The Azure provider does not offer equivalent default tags; use Azure Policy to enforce tag inheritance for Azure resources.
The following is an example using default tags:
provider "aws" {
profile = "default"
region = "us-east-2"
default_tags {
tags = {
Environment = "Test"
Service = "Payment API"
}
}
}
The default_tags block applies Environment and Service tags to every resource the AWS provider creates in this configuration. Individual resources can override or extend these defaults in their own tags blocks, giving you a consistent baseline without losing per-resource flexibility.
Enforce tagging strategy policies
After you define your tagging strategy in code, you can enforce it to block non-compliant resources.
Use the Terraform validation block
You can use the Terraform validation block to enforce tagging policies. The validation block lets you define custom validation rules for input variables. You can use the validation block to ensure that the resources you tag follow your tagging strategy.
The following is an example of a Terraform validation block that ensures the environment tag is set to either dev, staging, or prod:
variable "environment" {
type = string
description = "Environment name for resource tagging"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be one of: dev, staging, prod."
}
}
This validation block runs before Terraform creates any resources. If the environment variable does not match one of the allowed values, Terraform returns the error_message and stops the plan, preventing a misconfigured resource from being deployed.
The following tag passes the validation:
environment = "prod"
A value of prod satisfies the validation block's condition, so Terraform proceeds with the plan.
The following tag fails the validation due to not meeting the condition of being dev, staging, or prod:
environment = "testing"
A value of testing is not in the allowed list, so Terraform returns an error before creating any resources.
Use policy as code
For more advanced enforcement, you can use policy as code tools such as HashiCorp Sentinel or the Open Policy Agent (OPA). These tools create policies that enforce tagging rules across your deployments. You can integrate these policies into your CI/CD pipelines or with HCP Terraform to ensure that all resources comply with your tagging strategy before deployment.
The following is an example of a Pass or Fail Sentinel policy that ensures that all AWS EC2 instances have a Name tag:
import "tfplan/v2" as tfplan
# Get all AWS instances from all modules
ec2_instances = filter tfplan.resource_changes as _, rc {
rc.type is "aws_instance" and
(rc.change.actions contains "create" or rc.change.actions is ["update"])
}
# Mandatory Instance Tags
mandatory_tags = [
"Name",
]
# Rule to enforce "Name" tag on all instances
mandatory_instance_tags = rule {
all ec2_instances as _, instance {
all mandatory_tags as mt {
instance.change.after.tags contains mt
}
}
}
main = rule {
mandatory_instance_tags else true
}
This Sentinel policy filters all aws_instance resource changes in the plan and verifies that each one includes a Name tag. If any EC2 instance is missing the tag, the policy fails and HCP Terraform blocks the apply. Expanding the mandatory_tags list lets you enforce additional required tags without changing the rule logic.
You can write similar policies with OPA and HCP Terraform.
HashiCorp resources
- Read the AWS provider resource tagging guide for supported tag arguments and provider-level configuration.
- Learn how to configure default tags for AWS resources using the
default_tagsprovider block. - Read the GCP provider default labels reference for applying default labels across Google Cloud resources.
- Read about the Terraform validation block for enforcing allowed values on input variables.
- Write a Sentinel policy for a Terraform deployment to ensure that the EC2 instance has a
Nametag. - Learn how to define Open Policy Agent policies for HCP Terraform
- Read the HCP Terraform policy enforcement overview
- Get started with Sentinel by exploring the tutorials.
External resources
- Use OPA to write policies that ensure all resources have tags before you create them.
Next steps
In this section of Lifecycle management, you learned how to tag resources using infrastructure as code and enforce tagging policies.
To continue building your lifecycle management practices, refer to the following resources:
- Read the Implement data management policies guide
- Read the Decommission resources guide