Optimizing Infrastructure Scalability Using Terraform's COUNT Argument


Introduction
Managing infrastructure at scale can be challenging, especially when deploying multiple similar resources. Terraform's count
argument simplifies this process by allowing you to create multiple instances of a resource or module using an incrementing index. This is particularly useful when deploying identical or nearly identical resources, such as EC2 instances across multiple subnets.
In this tutorial, you'll:
Provision a VPC, load balancer, and EC2 instances on AWS.
Use the
count
argument to dynamically deploy multiple EC2 instances in each private subnet.Refactor Terraform configurations to improve scalability and maintainability.
Prerequisites
Before starting, ensure you have the following:
✅ Latest version of Terraform installed
✅ An AWS Account with IAM permissions to create VPCs, EC2 instances, and load balancers
✅ HCP Terraform (formerly Terraform Cloud) account
✅ VS Code (or any preferred code editor)
✅ AWS CLI configured (optional, but recommended for testing)
export AWS_ACCESS_KEY_ID="your_access_key" export AWS_SECRET_ACCESS_KEY="your_secret_key"
Step 1: Clone the Starter Repository
Start by cloning the example repository:
git clone https://github.com/hashicorp-education/learn-terraform-count
cd learn-terraform-count
This repository contains a basic Terraform configuration for:
A VPC with public and private subnets
An Application Load Balancer (ALB)
EC2 instances in private subnets
Step 2: Initialize and Apply the Configuration
Set your HCP Terraform organization name (replace
<YOUR_ORG>
):export TF_CLOUD_ORGANIZATION=<YOUR_ORG>
Initialize Terraform:
terraform init
Apply the configuration:
terraform apply
At this point, the configuration deploys only one EC2 instance per private subnet, which isn't scalable.
Step 3: Refactor the Configuration for Scalability
Problem with the Current Setup
The initial configuration hardcodes EC2 instances (app_a
, app_b
), making it inflexible. If you increase private_subnets_per_vpc
, new instances won’t be created automatically.
Solution: Use count
for Dynamic Scaling
Declare a new variable in
variables.tf
:variable "instances_per_subnet" { description = "Number of EC2 instances per private subnet" type = number default = 2 # Default: 2 instances per subnet }
Refactor the EC2 resource block in
main.tf
:Remove hardcoded instances (
app_a
,app_b
).Replace with a single
aws_instance
block usingcount
:
resource "aws_instance" "app" {
count = var.instances_per_subnet * length(module.vpc.private_subnets)
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
subnet_id = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]
tags = {
Name = "app-instance-${count.index}"
}
}
How This Works:
count.index
assigns a unique index (0, 1, 2, ...) to each instance.Modulo (
%
) ensures instances are distributed evenly across subnets.
Update the Load Balancer Configuration:
Modify theaws_lb_target_group_attachment
to dynamically attach all instances:resource "aws_lb_target_group_attachment" "app" { count = length(aws_instance.app) target_group_arn = aws_lb_target_group.app.arn target_id = aws_instance.app[count.index].id }
Update Outputs:
Modifyoutputs.tf
to list all instance IDs:output "instance_ids" { value = aws_instance.app[*].id }
Step 4: Test the Scalable Configuration
Run
terraform plan
to preview changes.Apply the updated configuration:
terraform apply
Now, Terraform will:
Deploy 2 instances per private subnet (default).
Distribute them evenly across subnets.
Automatically attach all instances to the load balancer.
Step 5: Adjust Scaling Dynamically
Want more instances per subnet? Just update the variable:
variable "instances_per_subnet" {
default = 3 # Now deploys 3 instances per subnet!
}
Re-run terraform apply
, and Terraform will adjust accordingly.
Best Practices When Using count
✔ Use for identical resources – If instances need different configurations, consider for_each
.
✔ Avoid hardcoding indexes – Use count.index
dynamically (e.g., subnet distribution).
✔ Combine with length()
– Makes the configuration adapt to list/map changes.
Conclusion
By using Terraform’s count
argument, you can:
Eliminate repetitive code (no more
app_a
,app_b
, etc.).Scale infrastructure dynamically (just update
instances_per_subnet
).Improve maintainability (fewer lines of code, easier updates).
Next steps:
Experiment with
for_each
for non-identical resources.Explore auto-scaling groups (ASGs) for even more flexibility.
🚀 Happy Terraforming!
Subscribe to my newsletter
Read articles from Joel Thompson directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
