Optimizing Infrastructure Scalability Using Terraform's COUNT Argument

Joel ThompsonJoel Thompson
3 min read

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)

  1.  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

  1. Set your HCP Terraform organization name (replace <YOUR_ORG>):

     export TF_CLOUD_ORGANIZATION=<YOUR_ORG>
    
  2. Initialize Terraform:

     terraform init
    
  3. 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

  1. 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
     }
    
  2. Refactor the EC2 resource block in main.tf:

    • Remove hardcoded instances (app_a, app_b).

    • Replace with a single aws_instance block using count:

    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.

  1. Update the Load Balancer Configuration:
    Modify the aws_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
     }
    
  2. Update Outputs:
    Modify outputs.tf to list all instance IDs:

     output "instance_ids" {
       value = aws_instance.app[*].id
     }
    

Step 4: Test the Scalable Configuration

  1. Run terraform plan to preview changes.

  2. 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!


0
Subscribe to my newsletter

Read articles from Joel Thompson directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Joel Thompson
Joel Thompson