How to use Terraform count, length, element and tolist
When working with Terraform often you need to manage dynamic infrastructure across multiple availability zones or resources and that requires looping. In order to do this effectively you need to learn how to use Terraform count, length, element and tolist. In this blog post we will simply introduce these and show how they work together by using simple example that targets multiple AWS network interfaces and attaches them to a load balancer.
Example
Here is a simplified example of the Terraform code we’ll use to explain these concepts:
data "aws_network_interface" "api_interface" {
count = length(element(module.context.aws_az_names, 0))
id = element(tolist(aws_vpc_endpoint.api_gateway.network_interface_ids), count.index)
}
resource "aws_lb_target_group_attachment" "private_tg" {
count = length(element(module.context.aws_az_names, 0))
target_group_arn = aws_lb_target_group.private_tg.arn
target_id = data.aws_network_interface.api_interface[count.index].private_ip
}Let’s dive into each part.
Explanation
The count meta-argument pretty much tells Terraform to create multiple instance of specific resource or data block. This is commonly used for looping when the number isn’t fixed.
In the example above we have:
count = length(element(module.context.aws_az_names, 0))What we do here is telling Terraform to check how many availability zones are listed in the first element which is aws_az_names and then loop that many times. For example if we have 3 AZs it would loop 3 times and that is useful for AZ specific resources.
We can break it down further. aws_az_names is output of the specific module and possibly look like this:
output "aws_az_names" {
value = data.aws_availability_zones.this[*].names
}Which in reality is something like this:
[[ "eu-central-1a", "eu-central-1b", "eu-central-1c" ]]
Then we have element on top of that. Since element use list and index but in our example it is a bit more complex instead we have list of lists so when we use element(list ,index) such as element(module.context.aws_az_names, 0) we are grabbing first one which is essentially list of AZs.
So this is more complex version of this feature:
locals {
fruits = ["apple", "banana", "cherry"]
}
output "favorite_fruit" {
value = element(local.fruits, 1)
}and the result would be favorite_fruit = “banana”. The length is going to simply count how many AZs there are in the list and in the end count is going to have that result which is 3 in such a case.
Now lets focus on next part:
id = element(tolist(aws_vpc_endpoint.api_gateway.network_interface_ids), count.index)The tolist() function ensures a set or tuple behave like an ordered list which is crucial because many Terraform functions require indexable structure and it this case element requires as well. What it does is that it assigns one network interface ID from the list of interface IDs attached to the api_gateway VPC endpoint based on the current index from count.index.
Since element expects list we make sure to pass a list to it and for index we pass count.index so that for each loop iteration count.index is 0, 1, 2, etc. So simplified this line tells Terraform give me the network interface ID that corresponds to this loop index.
Conclusion
By learning how to use Terraform count, length, element and tolist
- count to iterate
- length to determine size
- element for easier access
- tolist for consistent structure
you can scale your infrastructure dynamically and reliably.
If this blog saved you time, support me with a coffee!
Thanks to everyone who’s supported!







