Join experts to dive deep into IaC security and governance on August 27

➡️ Register for IaCConf

Terraform

How to Use Tags in Terraform? [Overview & Examples]

terraform tags

🚀 Level Up Your Infrastructure Skills

You focus on building. We’ll keep you updated. Get curated infrastructure insights that help you make smarter decisions.

In this article, we will look at how to use tags with Terraform. We will explain what they are and why you might use them with some use case examples before moving on to practical examples of how to tag resources on AWS. 

What we will cover:

  1. What are tags in Terraform?
  2. Use cases for tags in Terraform
  3. How to manage resource tags using Terraform?
  4. How to add multiple tags to Terraform resources?
  5. What are Terraform default tags?
  6. How to ignore changes to Terraform to tags?
  7. How to merge Terraform tags?
  8. Provider differences in Terraform tags
  9. Tagging shared resources on AWS
  10. Best practices for Terraform tags

What are tags in Terraform?

Tags in Terraform are key-value pairs associated with cloud resources. They allow you to categorize and organize these resources for better management, cost allocation, environment identification (e.g., production, staging, development), and automation. The keys can be anything you choose as long as they don’t conflict with any reserved keys from your cloud provider.

For cloud providers like AWS, Azure, and Google Cloud, Terraform leverages these tags to associate metadata with resources such as instances, networks, or databases. The key represents the category (e.g., “Environment”), while the value specifies the detail (e.g., “Production”).

Tags are implemented differently depending on the cloud provider you’re using. However, Terraform itself offers ways to set and manage tags consistently across providers using the tags attribute of a resource.

What is the difference between tags and tags_all in Terraform?

Terraform tags sets or overrides tags directly on a resource, while tags_all reflects the combined set of tags, including provider-level defaults. If a provider defines default tags via the default_tags block, those are automatically merged into tags_all but not into tags unless explicitly added.

For example, if you had an Azure VNet called example that you wanted to reference the tags on, you could use azurerm_virtual_network.example.tags_all.

Use cases for tags in Terraform

Tags are often used to apply metadata to resources, making it easier to identify, manage, and track costs. They can also help categorize resources by ownership, environment, project, or other criteria.

  1. Organization: Terraform tags help organize and group specific resources, making locating them within a large set easier.

Example tags:

    • env = "production"
    • owner = "team-abc"
    • purpose = "web-server"
  1. Cost management: You can use Terraform tags to identify resources associated with a particular project or cost center.

Example tag:

    • cost_center = "sales"

Consider tagging resources that have assigned reserved instances.

  1. Automation: Tags can be used to automate deployments or configurations based on specific tags. For example, you might only deploy resources with the tag deploy = "true" during a production rollout. 

You could also use them to enable targeting with configuration management tools such as Chef and Ansible or to denote which DevOps deployment strategy has been used.

Example tags:

    • auto_shutdown = "true"
    • deploy = "true"
    • ansible_managed = "true"
    • deployment = "bluegreen"
  1. Access control: Tags can be used to define access control policies, ensuring that only authorized users or groups can manage specific resources. 

For example, you could tag resources in the development environment with the key “Environment” and the value “Development.” Then, in the AWS IAM console, create a policy that allows the “DevOps” group to access resources with the “Environment” tag set to “Development.” 

Note that tag-based access control might not be the most granular approach. It’s often best used in conjunction with other IAM roles and permissions.

  1. Disaster recovery and backup: Tags help manage disaster recovery and backup processes. For example:
    • backup = "monthly"
  1. Compliance: You can mark resources that need to comply with specific regulations. For example:
    • gdpr = "true"
    • iso27001 = "true"

How to add tags to Terraform resources?

You can use the tags attribute to specify the map of key-value pairs you want to use as tags.

  • tags – (Optional) A mapping of tags to assign to the resource.

Each key in the map represents the tag name, and the corresponding value is the tag content.

Here are the basic steps for adding tags to resources in Terraform:

  1. Check if the resource supports tags (not all Terraform resources support tags)
  2. Add a tags block
  3. Define the key-value pairs (you can specify multiple tags by defining key-value pairs inside the tags block)

Example: Using tags in Terraform

This code snippet adds a tag to a resource, where the key is Environment and the value is Development.

tags = {
  Environment = "Development"
}

How to add multiple tags to Terraform resources?

You can include multiple key-value pairs inside the tags block to add multiple tags to Terraform resources. Each tag consists of a unique key and its corresponding value.

For example:

tags = {
  Environment = "Development"
  Owner       = "Luke Skywalker"
  Department  = "Jedi Order"
}

What are Terraform default tags?

Default tags in Terraform refer to tags applied to all or most of the resources in your configuration. These can be defined at a higher level (e.g., through variables or modules) to avoid repetition and ensure consistency across resources. You can define default tags either by setting them globally through variables or directly within each resource.

For example, to define tags in the variable defaults:

variable "common_tags" {
  type = map(string)
  default = {
    Environment = "Development"
  }
}

tags = var.common_tags

How to override the default tags?

If you want to override the default tags with custom tags for specific resources, you can do this by explicitly defining the tags argument in the resource definition.

 

  • Override at the resource level: If default tags are applied via the provider or module, you can add or change specific tags directly within the resource block.
  • Merge default and custom tags: Use Terraform functions like merge() to combine the default tags with custom tags while giving priority to the custom ones.

How to ignore changes to Terraform tags?

Suppose external systems interact with resource tags (e.g., Configuration Management Databases or your cloud adds auto-generated tags for certain resources, such as Azure Databricks). In that case, you can configure Terraform to ignore changes to specific tags. This prevents Terraform from showing unexpected changes in your Terraform plan.

To ignore changes to Terraform tags, you can use the lifecycle block in your resource definition, which is the most common approach and works for all Terraform resources. Simply set the value of ignore_changes to "tags" to ignore all tag changes. 

Using ignore_changes can be helpful, but it’s essential to understand why tags are being modified externally and ensure these external modifications are consistent with your infrastructure management practices.

resource "aws_instance" "my_instance" {
  # ... other configuration options

  lifecycle {
    ignore_changes = [tags]
  }
}

Some Terraform providers, like the AWS provider, offer a provider-level configuration option called ignore_tags. This option applies to all resources that provider manages in your Terraform configuration.

provider "aws" {
  # ... other configuration options

  ignore_tags = [
    "CostCenter",  # Ignore changes to tags with this key
  ]
}

How to merge Terraform tags?

One useful application of the merge function in Terraform is adding additional tags to resources to combine with your default set of tags. The merge() function combines multiple maps (key-value pairs), and tags are typically defined as a map.

In this example, a tag is set as the default in the variable, and the merge function is used to add a name tag using the tags attribute in the resource.

variable "common_tags" {
  type = map(string)
  default = {
    Environment = "Development"
  }
}

resource "aws_instance" "my_instance" {
  # ... other configuration options

  tags = merge(var.common_tags, {
    Name = "My Web Server"
  })
}

Provider differences in Terraform tags

Tag implementation in Terraform varies by provider due to differences in metadata handling and resource tagging capabilities. Key differences involve default tag behavior, inheritance, and consistency across services.

  • AWS: The AWS provider supports default tags via the default_tags block. These apply to most taggable resources automatically, and explicit tags override defaults. Some services still lack tagging support or have delayed propagation.
  • Azure: Azure does not support provider-level default tags in Terraform. Tags must be defined per resource using the tags block. Tag names and values are case-sensitive, and inheritance from resource groups is not automatic.
  • Google Cloud (GCP): GCP uses labels (for resource metadata) and network tags (for networking purposes). Terraform primarily manages labels. There is no provider-level default label feature, and label support is inconsistent across resource types.

Tagging shared resources on AWS

As of version 3.38.0 of the Terraform AWS provider, the Terraform Configuration Language also enables provider-level tagging. Instead of defining tags on each resource, you can set them at the provider level, and they will propagate down to all supported resources automatically (except for scale sets), keeping your code clean and reducing duplication. 

If you want to apply individual tags in addition to the default set, you can still use the AWS tags attribute on the resource in question and these will get added to the set. In the example below, the aws_vpc resource will be assigned all four tags.

provider "aws" {
  # ... other configuration ...
  default_tags {
    tags = {
      Environment = "Development"
      Owner       = "Luke Skywalker"
      Department  = "Jedi Order"
    }
  }
}

resource "aws_vpc" "example" {
# ... other configuration ...
  tags = {
    VNET_Name = "Dagobah system VNET"
  }
}

Best practices for Terraform tags

Defining a tagging strategy at the start of your project deployment is definitely a good idea to avoid any rework.

  • Consistency Ensure that the same key names are consistently used across different resources for better organization. It’s important to find the right balance when determining the level of detail for your tags. While too many tags can be overwhelming, too few can make it difficult to effectively organize and retrieve information.
  • Documentation Document your tagging strategy and maintain a tagging convention.
  • Automation  Use Terraform modules or scripts to automate tagging and ensure that all resources are tagged correctly.
  • Leverage Terraform default tags Terraform allows you to define default tags in the AWS provider section. These default tags are automatically applied to all AWS resources created by Terraform. By defining default tags in one code location, you follow the best practice of DRY (Don’t Repeat Yourself).

Deploying Terraform resources with Spacelift

Terraform is really powerful, but to achieve an end-to-end secure GitOps approach, you need to use a product that can run your Terraform workflows. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:

  • Policies (based on Open Policy Agent) – You can control how many approvals you need for runs, what kind of resources you can create, and what kind of parameters these resources can have, and you can also control the behavior when a pull request is open or merged.
  • Multi-IaC workflows – Combine Terraform with Kubernetes, Ansible, and other infrastructure-as-code (IaC) tools such as OpenTofu, Pulumi, and CloudFormation,  create dependencies among them, and share outputs
  • Build self-service infrastructure – You can use Blueprints to build self-service infrastructure; simply complete a form to provision infrastructure based on Terraform and other supported tools.
  • Integrations with any third-party tools – You can integrate with your favorite third-party tools and even build policies for them. For example, see how to Integrate security tools in your workflows using Custom Inputs.

Spacelift enables you to create private workers inside your infrastructure, which helps you execute Spacelift-related workflows on your end. For more information on configuring private workers, refer to the documentation.

You can check it for free by creating a trial account or booking a demo with one of our engineers.

Key points

Terraform tags represent key-value pairs assigned to resources to improve resource categorization, cost management, and automation. They are widely used in cloud environments for optimizing infrastructure operations. A well-thought-out tagging strategy forms the backbone of successful cloud governance and resource optimization.

Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Frequently asked questions

What does ~> mean in Terraform?

In Terraform, ~> is the pessimistic constraint operator used for versioning. It allows updates within the same major or minor version but prevents breaking changes. For example, ~> 2.1 means any version >= 2.1.0 and < 3.0.0. Similarly, ~> 2.1.3 allows versions < 2.2.0. This helps ensure compatibility without locking to a single patch.

How do you ignore certain tags in Terraform?

Add a lifecycle block to the resource and list the attributes (or specific tag keys) Terraform should ignore. The ignore_changes meta-argument tells Terraform to disregard those attributes on updates while still respecting them at creation time.

Why did my Terraform tags disappear?

Tags in Terraform often disappear due to one of the following causes:

  • A module, resource, or provider update overwrote or ignored tags not explicitly defined in the code.
  • Default tags defined at the provider level were removed or not merged correctly.
  • Tags were managed outside Terraform, and a terraform apply reverted them.
  • Tag keys had dynamic values that evaluated to null or empty strings, causing them to be dropped.
  • A for_each or merge() function in your tag logic excluded expected keys during evaluation.

How can I tag all existing Terraform resources?

To tag all existing Terraform-managed resources, update your Terraform configuration to include the desired tags in each resource block or use provider-level default tags if supported (e.g., default_tags in AWS). Then run terraform plan and terraform apply to update the tags in place without recreating resources.

Keep in mind:

  • Any objects Terraform isn’t already managing must be imported (CLI terraform import or the import { … } block in Terraform ≥ 1.6) before the new tags can be applied.
  • Not all resources support tag updates without replacement.
  • Use lifecycle { ignore_changes = [tags] } cautiously if avoiding drift is important.
  • For bulk updates, modules or automation can help inject standard tags consistently.

What is etag in Terraform?

etag is a server-supplied fingerprint used for optimistic concurrency control. Terraform includes the etag value on updates. If the remote object’s etag has changed (someone else modified it), the provider raises a conflict instead of overwriting the change. For example, Google IAM resources expose a computed etag, and S3 objects expose their MD5 (or multipart) hash as etag.

Not every resource supports etag. Where absent, the provider handles locking internally or relies on the API’s idempotency.

Automate Terraform deployments with Spacelift

Automate your infrastructure provisioning, build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.

Learn more

Terraform Commands Cheat Sheet

Grab our ultimate cheat sheet PDF
for all the Terraform commands
and concepts you need.

Share your data and download the cheat sheet