| --- |
| page_title: The count Meta-Argument - Configuration Language |
| description: >- |
| Count helps you efficiently manage nearly identical infrastructure resources |
| without writing a separate block for each one. |
| --- |
| |
| # The `count` Meta-Argument |
| |
| -> **Version note:** Module support for `count` was added in Terraform 0.13, and |
| previous versions can only use it with resources. |
| |
| -> **Note:** A given resource or module block cannot use both `count` and `for_each`. |
| |
| > **Hands-on:** Try the [Manage Similar Resources With Count](/terraform/tutorials/0-13/count?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial. |
| |
| By default, a [resource block](/terraform/language/resources/syntax) configures one real |
| infrastructure object. (Similarly, a |
| [module block](/terraform/language/modules/syntax) includes a |
| child module's contents into the configuration one time.) |
| However, sometimes you want to manage several similar objects (like a fixed |
| pool of compute instances) without writing a separate block for each one. |
| Terraform has two ways to do this: |
| `count` and [`for_each`](/terraform/language/meta-arguments/for_each). |
| |
| If a resource or module block includes a `count` argument whose value is a whole number, |
| Terraform will create that many instances. |
| |
| ## Basic Syntax |
| |
| `count` is a meta-argument defined by the Terraform language. It can be used |
| with modules and with every resource type. |
| |
| The `count` meta-argument accepts a whole number, and creates that many |
| instances of the resource or module. Each instance has a distinct infrastructure object |
| associated with it, and each is separately created, |
| updated, or destroyed when the configuration is applied. |
| |
| ```hcl |
| resource "aws_instance" "server" { |
| count = 4 # create four similar EC2 instances |
| |
| ami = "ami-a1b2c3d4" |
| instance_type = "t2.micro" |
| |
| tags = { |
| Name = "Server ${count.index}" |
| } |
| } |
| ``` |
| |
| ## The `count` Object |
| |
| In blocks where `count` is set, an additional `count` object is |
| available in expressions, so you can modify the configuration of each instance. |
| This object has one attribute: |
| |
| - `count.index` — The distinct index number (starting with `0`) corresponding |
| to this instance. |
| |
| ## Using Expressions in `count` |
| |
| The `count` meta-argument accepts numeric [expressions](/terraform/language/expressions). |
| However, unlike most arguments, the `count` value must be known |
| _before_ Terraform performs any remote resource actions. This means `count` |
| can't refer to any resource attributes that aren't known until after a |
| configuration is applied (such as a unique ID generated by the remote API when |
| an object is created). |
| |
| ## Referring to Instances |
| |
| When `count` is set, Terraform distinguishes between the block itself |
| and the multiple _resource or module instances_ associated with it. Instances are |
| identified by an index number, starting with `0`. |
| |
| - `<TYPE>.<NAME>` or `module.<NAME>` (for example, `aws_instance.server`) refers to the resource block. |
| - `<TYPE>.<NAME>[<INDEX>]` or `module.<NAME>[<INDEX>]` (for example, `aws_instance.server[0]`, |
| `aws_instance.server[1]`, etc.) refers to individual instances. |
| |
| This is different from resources and modules without `count` or `for_each`, which can be |
| referenced without an index or key. |
| |
| Similarly, resources from child modules with multiple instances are prefixed |
| with `module.<NAME>[<KEY>]` when displayed in plan output and elsewhere in the UI. |
| For a module without `count` or `for_each`, the address will not contain |
| the module index as the module's name suffices to reference the module. |
| |
| -> **Note:** Within nested `provisioner` or `connection` blocks, the special |
| `self` object refers to the current _resource instance,_ not the resource block |
| as a whole. |
| |
| ## When to Use `for_each` Instead of `count` |
| |
| If your instances are almost identical, `count` is appropriate. If some |
| of their arguments need distinct values that can't be directly derived from an |
| integer, it's safer to use `for_each`. |
| |
| Before `for_each` was available, it was common to derive `count` from the |
| length of a list and use `count.index` to look up the original list value: |
| |
| ```hcl |
| variable "subnet_ids" { |
| type = list(string) |
| } |
| |
| resource "aws_instance" "server" { |
| # Create one instance for each subnet |
| count = length(var.subnet_ids) |
| |
| ami = "ami-a1b2c3d4" |
| instance_type = "t2.micro" |
| subnet_id = var.subnet_ids[count.index] |
| |
| tags = { |
| Name = "Server ${count.index}" |
| } |
| } |
| ``` |
| |
| This was fragile, because the resource instances were still identified by their |
| _index_ instead of the string values in the list. If an element was removed from |
| the middle of the list, every instance _after_ that element would see its |
| `subnet_id` value change, resulting in more remote object changes than intended. |
| Using `for_each` gives the same flexibility without the extra churn. |