Skip to main content

Using Count Meta-Argument

1. Creating Multiple Resources

Property Description Values Notes
count Defines the number of instances to create number Must be a positive integer or a reference to a variable

Example: Creating Multiple S3 Buckets

resource "aws_s3_bucket" "bucket" {
  count = 3
  bucket = "my-bucket-${count.index}"
}
Note: The count.index variable provides the index of each instance (0, 1, 2...).
Warning: Changing the count value will cause Terraform to destroy and recreate resources, potentially leading to data loss.

Key Points

  • count creates multiple instances of a resource
  • Each instance has a unique count.index value
  • Changing count triggers resource recreation

2. Referencing Count Index

Reference Type Syntax Description
count.index count.index Index of the current instance in the count loop (0-based)
count.key count.key Key of the current instance (only for for_each)

Example: Using count.index in resource configuration

resource "aws_instance" "web" {
  count = 3
  ami           = "ami-12345678"
  instance_type = "t2.micro"
  tags = {
    Name = "web-${count.index}"
  }
}
Note: count.index is useful for creating unique resource names or assigning distinct values to each instance in a count loop.

3. Using Conditional Resource Creation (count = condition ? 1 : 0)

Use the count meta-argument with a conditional expression to conditionally create resources based on a boolean condition.

Property Description Example
count Number of instances to create. If 0, no resources are created. count = var.create_instance ? 1 : 0

Example: Conditional EC2 Instance Creation

resource "aws_instance" "web" {
  count = var.create_web_server ? 1 : 0
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}
Note: When count = 0, the resource is completely skipped and not managed by Terraform.
Warning: Using count = 0 does not prevent dependencies from being evaluated. If a resource depends on this conditional resource, it will still be processed.

4. Accessing Count Resources

Resource Reference Syntax Description
resource.type.name aws_instance.web[0] Access the first instance in a count loop
resource.type.name aws_instance.web[1] Access the second instance in a count loop
resource.type.name aws_instance.web[count.index] Access resource by index variable

Example: Accessing Count Resources in Variables

variable "instance_ids" {
  type = list(string)
  default = [for instance in aws_instance.web : instance.id]
}

output "first_instance_id" {
  value = aws_instance.web[0].id
}
Note: When using count.index, ensure that the resource count is known at apply time to avoid runtime errors.

5. Understanding Count Limitations

Limitation Description Impact
Index Availability Count creates a list of resources, but individual resource indexes are not directly accessible in some contexts (e.g., within for_each loops or complex expressions). Requires careful use of count.index for referencing specific instances.
State Management Changing the count value causes Terraform to destroy and recreate resources, which can lead to data loss if not handled carefully. State drift and potential downtime during updates.
Conditional Logic Using count with conditional logic (e.g., count.index < 5) can make state management more complex and harder to predict. Increased risk of misconfiguration and unexpected behavior in state files.
Resource Dependencies When using count, dependencies between resources must be explicitly defined to avoid unintended order of operations. Potential for race conditions or incorrect resource creation order.
Note: count is not suitable for all use cases. For more dynamic resource creation, consider using for_each or custom modules.
Warning: Modifying the count value in an existing configuration can cause resource recreation and data loss. Always back up your state before making such changes.

6. Using Count with Modules

Property Description Example
count Number of instances to create for a module count = 3
count.index Index of the current module instance (0-based) count.index

Example: Creating Multiple S3 Buckets

module "bucket" {
  source = "./s3-bucket"
  count  = 3
  name   = "my-bucket-${count.index}"
}
Note: When using count with modules, the module instances are created in order, and count.index can be used to differentiate each instance.
Warning: Changing the count value can cause Terraform to destroy and recreate resources, leading to data loss. Always verify the plan before applying changes.

7. Handling Count Changes

Change Type Description Impact Action Required
count = 0 Resource is destroyed Resource instance removed from state None, unless dependencies exist
count = 1 → count = 3 Resource instances created New instances added to state Review new instances for configuration
count = 3 → count = 1 Resource instances destroyed Instances removed from state Ensure data is backed up or migrated
count = 2 → count = 2 (same) No change in count State unchanged None

Example: Changing Count Value

resource "aws_instance" "web" {
  count = 3
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}
Note: When count changes, Terraform will destroy and recreate resources in a way that preserves state for each instance.
Warning: Changing count from a non-zero value to zero will destroy all instances. Ensure backups or data migration are in place.

8. Combining Count with Conditionals

Property Description Usage
count Controls how many instances of a resource to create count = 3
count.index Index of the current resource instance (0-based) count.index
count.value Value of the count variable (only available in loops) count.value

Example: Conditional Resource Creation with Count

resource "aws_instance" "web" {
  count = var.create_web_servers ? 2 : 0

  ami           = "ami-12345678"
  instance_type = "t2.micro"

  tags = {
    Name = "web-${count.index}"
  }
}

Example: Using Count with Conditionals in Variables

variable "create_servers" {
  description = "Whether to create servers or not"
  type        = bool
  default     = true
}

resource "aws_instance" "app" {
  count = var.create_servers ? 3 : 0

  ami           = "ami-87654321"
  instance_type = "t3.micro"

  tags = {
    Name = "app-${count.index}"
  }
}
Note: When using count with conditionals, ensure that the conditional logic evaluates to a number or boolean. If you're using a variable that might be null, use var.name != null to check for existence before applying the conditional.
Warning: Changing count from a number to zero or vice versa will cause Terraform to destroy and recreate resources, which can lead to data loss. Always verify the impact before making such changes.

9. Using Count with Data Sources

Property Description Example
count Number of instances to create from a data source count = 3
for_each Iterate over a map or set to create multiple data source instances for_each = var.instances

Example: Using count with data sources

data "aws_subnet" "subnet" {
  count = 3
  id = aws_subnet.subnet_ids[count.index]
}

output "subnet_ids" {
  value = data.aws_subnet.subnet[*].id
}
Note: When using count with data sources, the index is accessible via count.index.

Example: Using for_each with data sources

data "aws_instance" "instance" {
  for_each = var.instances
  instance_id = each.value.id
}

output "instance_ids" {
  value = [for instance in data.aws_instance.instance : instance.id]
}
Warning: Changing count or for_each values can cause data source re-creation, which may lead to data loss or unexpected behavior.

10. Converting Count to For-Each

Aspect Count For-Each
Usage count = 3 for_each = var.instances
Index Access count.index for_each.key
Resource Reference aws_instance.example[count.index] aws_instance.example[for_each.key]
Behavior on Change Recreates resources if count changes Updates resources if for_each map changes

Example: Converting Count to For-Each

# Before (using count)
resource "aws_instance" "example" {
  count = 3
  ami           = "ami-12345678"
  instance_type = "t2.micro"
  tags = {
    Name = "instance-${count.index}"
  }
}

# After (using for_each)
variable "instances" {
  default = [ "web", "db", "app" ]
}

resource "aws_instance" "example" {
  for_each = var.instances
  ami           = "ami-12345678"
  instance_type = "t2.micro"
  tags = {
    Name = "instance-${for_each.key}"
  }
}
Note: for_each is preferred over count for managing multiple resources with different configurations.
Warning: Changing the for_each map will cause all resources to be recreated if not handled carefully.

Was this article helpful?