> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using count

> Explains Terraform's count meta-argument for creating indexed resource instances, discusses identity, lifecycle pitfalls, and when to prefer for_each for stable, key based resource identities.

In this lesson we cover one of Terraform's earliest and simplest iteration mechanisms: the `count` meta-argument. `count` is useful for creating multiple copies of a resource from a single block, but it has important implications for identity, indexing, and lifecycle behavior. Read on for concise examples, common pitfalls, and guidance on when to prefer alternatives like `for_each`.

What `count` does

* Adding `count = N` transforms a single resource block into a collection (a list) of `N` instances rather than a single instance.
* Inside such a resource block you can reference `count.index` to get the current instance’s numeric index (starting at `0`).
* Each instance’s identity is positional and based on its numeric index — Terraform tracks `resource.name[0]`, `resource.name[1]`, etc., not by any human-readable name you assign.

Example: two resource groups

```hcl theme={null}
resource "azurerm_resource_group" "rg" {
  count    = 2
  name     = "rg-${count.index}"
  location = "eastus"
}
```

This creates:

* `azurerm_resource_group.rg[0]` with name `rg-0`
* `azurerm_resource_group.rg[1]` with name `rg-1`

`count.index` exists only inside resource blocks that use `count` and increments from `0` to `count - 1`.

<Callout icon="lightbulb" color="#1CB2FE">
  Use `count` when instance identity is strictly positional (index-based) and you only need simple duplication with small index-driven differences (for example, suffixes or offsets). For long-lived infrastructure that requires stable identities, prefer `for_each`.
</Callout>

When `count` is a poor fit

* Identity is numeric and positional. If you change `count`, Terraform will add or remove instances based on indices (it removes the highest indices first), not by any name or metadata you supply.
* Non-index-based mappings between configuration and logical entities can result in surprising destroys and recreates when indexes shift.

Practical examples

1. Minimal provider + counted resource groups

```hcl theme={null}
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
}

variable "subscription_id" {
  type = string
}

variable "text" {
  default = "rg"
}

resource "azurerm_resource_group" "rg" {
  count    = 3
  name     = "${var.text}-resources-${count.index}"
  location = "westeurope"
}
```

Terraform plan (simplified):

```bash theme={null}
# azurerm_resource_group.rg[0] will be created
+ resource "azurerm_resource_group" "rg" {
    + id       = (known after apply)
    + location = "westeurope"
    + name     = "rg-resources-0"
  }

# azurerm_resource_group.rg[1] will be created
+ resource "azurerm_resource_group" "rg" {
    + id       = (known after apply)
    + location = "westeurope"
    + name     = "rg-resources-1"
  }

# azurerm_resource_group.rg[2] will be created
+ resource "azurerm_resource_group" "rg" {
    + id       = (known after apply)
    + location = "westeurope"
    + name     = "rg-resources-2"
  }

Plan: 3 to add, 0 to change, 0 to destroy.
```

2. Creating a related resource per index

To create one storage account per resource group when both use `count`, use the same index so instances map 1:1:

```hcl theme={null}
resource "azurerm_storage_account" "sa" {
  count                     = 3
  name                      = "stfx${count.index}"
  resource_group_name       = azurerm_resource_group.rg[count.index].name
  location                  = azurerm_resource_group.rg[count.index].location
  account_tier              = "Standard"
  account_replication_type  = "LRS"
}
```

This maps `sa[0]` → `rg[0]`, `sa[1]` → `rg[1]`, and so on. Using matching indexes is a straightforward approach when instances should be paired by position.

3. Binding all instances to a single (first) resource group

If instead you reference a single index explicitly, all of your resources can be tied to that specific instance:

```hcl theme={null}
resource "azurerm_storage_account" "sa" {
  name                = "stfx0"
  resource_group_name = azurerm_resource_group.rg[0].name
  location            = azurerm_resource_group.rg[0].location
  account_tier        = "Standard"
  account_replication_type = "LRS"
}
```

If `sa` uses `count`, every `sa[i]` will be bound to `rg[0]`. If `sa` does not use `count`, this resource is simply created once in `rg[0]`.

Reducing `count` and the destroy behavior

* Decreasing `count` from `3` to `2` on `azurerm_resource_group.rg` causes Terraform to plan to destroy `rg[2]` (the highest index), because identities are positional. Example plan when decreasing:

```bash theme={null}
# azurerm_resource_group.rg[2] will be destroyed
- resource "azurerm_resource_group" "rg" {
    - id       = "/subscriptions/.../resourceGroups/rg-resources-2" -> null
    - location = "westeurope" -> null
    - name     = "rg-resources-2" -> null
  }

Plan: 0 to add, 0 to change, 1 to destroy.
```

Targeting and dependent resources

* Removing a middle index (for example `rg[1]`) is non-trivial. A targeted destroy like:

```bash theme={null}
terraform destroy --target 'azurerm_resource_group.rg[1]'
```

may still affect other resources. Terraform recalculates dependencies and the collection-level state, so dependent resources can be refreshed, recreated, or destroyed if their references or the collection’s structure change.

Important takeaway: targeted operations on counted collections can trigger complex cascades because Terraform maintains collection-level identity and dependency relationships. Removing a middle item often results in recomputations or recreations to keep indices consistent.

Why `for_each` is often better

* `count` uses numeric, positional identity.
* `for_each` uses stable keys (map keys or set elements) to give each instance a stable identity. With `for_each`, reordering, partial removals, or additions are less likely to cause unintended resource recreations.

Comparison at a glance

| Feature        |                                                    `count` | `for_each`                                                             |
| -------------- | ---------------------------------------------------------: | ---------------------------------------------------------------------- |
| Identity model |                                 Numeric index (positional) | Stable key (map/set element)                                           |
| Good for       |            Simple duplication with index-based differences | Stable, key-based instances that survive reordering/removal            |
| Changing size  | Removes highest indices first; middle removals are complex | Removing a key removes that specific instance without shifting others  |
| Best use case  |       Short-lived or ephemeral infrastructure, quick demos | Long-lived infra where individual resource identity must remain stable |

<Callout icon="warning" color="#FF6B6B">
  Avoid using `count` for resources where instance identity must remain stable across reorders, removals, or updates. Prefer `for_each` when you need deterministic, key-based identities for individual instances.
</Callout>

Summary

* `count` is a simple and effective way to duplicate resources when instance identity is purely positional.
* Instances are identified by `index` (0..N-1). Changes to `count` add or remove instances at the end of the list.
* Removing a middle instance can lead to unintended destroys or recreations because identity is positional.
* For stable identities and safer updates, use `for_each`.

Links and references

* Official Terraform docs: [https://www.terraform.io/docs](https://www.terraform.io/docs)
* `for_each` vs `count` guidance: [https://www.terraform.io/docs/language/meta-arguments/count.html](https://www.terraform.io/docs/language/meta-arguments/count.html)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/terraform-on-azure/module/fb5019bb-df21-4583-818e-6dae40fde2ec/lesson/7200843c-0c99-4508-95e2-14e9dac71d63" />
</CardGroup>
