Infrastructure as code for Amazon Elastic Container Service autoscaling requires explicit registration of the service with the Application Auto Scaling service and the creation of scaling policies that govern desired count adjustments. The configuration spans the ECS cluster definition, the ECS service definition, the autoscaling target resource, the autoscaling policy resource, and the IAM permissions that allow the autoscaling service to modify the service. Terraform provides resources for each of these steps and enables the entire setup to be versioned, reviewed, and reproduced.
The reference implementation describes an ECS cluster named example-cluster. The ECS service named my-service is attached to that cluster and references a task definition. The desiredcount is set to 1 in the Terraform configuration. The service is then registered for autoscaling with a minimum capacity of 1 and a maximum capacity of 10. The scalable dimension is ecs:service:DesiredCount and the service namespace is ecs. The resourceid follows the pattern service/my-cluster/my-service.
The scaling policy is created as a TargetTrackingScaling policy type with a name cpu-policy. The policy references the autoscaling target resource id, scalable dimension, and service namespace. The target tracking scaling policy configuration specifies a targetvalue of 50 and a customized metric specification with metricname CPUUtilization, namespace AWS/ECS, and statistic.
The application autoscaling target resource is awsappautoscalingtarget with maxcapacity 10, mincapacity 1, resourceid service/my-cluster/my-service, scalabledimension ecs:service:DesiredCount, service_namespace ecs.
The application autoscaling policy resource is awsappautoscalingpolicy with name cpu-policy, policytype TargetTrackingScaling, resourceid from the target, scalable dimension from the target, service namespace from the target, and a targettrackingscalingpolicyconfiguration block.
The ECS service resource includes an autoscale block with mincapacity 1 and maxcapacity 10. The desired_count is set to 1.
The post notes that Terraform Configuration for Service Autoscaling involves three steps: Define the ECS Service, Create Autoscaling Policies, Attach Autoscaling to ECS Service.
Service Autoscaling Fundamentals
Service Autoscaling automatically scales the number of tasks in an ECS service to meet demand.
Amazon ECS offers several autoscaling mechanisms to handle varying workloads for containerized applications. Each type of scaling targets different aspects of the infrastructure to ensure the application remains responsive under load.
The primary types of autoscaling in ECS include Service Autoscaling which adjusts the number of task instances within a specific ECS service, Cluster Autoscaling also known as Managed Scaling which modifies the number of EC2 instances in an ECS cluster when running EC2-backed clusters, and Target Tracking and Step Scaling Policies which offer two main policy types to control scaling behavior.
Service Autoscaling is helpful for applications with variable workloads where you want the service to scale automatically based on CPU, memory, or custom CloudWatch metrics.
AWS uses Cloudwatch metrics to check the average CPU/Memory of tasks to increase the desired count value. You can also use these metrics to decrease the desired count to save money during low usage times. ECS sends metrics every minute to Cloudwatch.
The ability to adjust the desired count of tasks in your ECS service is the core definition of ECS Autoscaling.
Types of Autoscaling in ECS
Service Autoscaling adjusts the number of task instances within a specific ECS service.
Cluster Autoscaling modifies the number of EC2 instances hosts in an ECS cluster when running EC2-backed clusters.
Target Tracking is based on metrics.
Step scaling is not recommended by AWS.
Scheduled scaling is based on date and time.
The post describes the main types of autoscaling ECS and how to configure them via terraform providing examples from which to take inspiration.
A Terraform module that provides intelligent auto scaling for ECS services based on Amazon SQS queue metrics exists as a community pattern.
The types of autoscaling can be summarized as follows:
| Type | Scope | Mechanism |
| Service Autoscaling | Number of tasks in a service | Adjusts desired count |
| Cluster Autoscaling | Number of EC2 instances in cluster | Managed Scaling for EC2 |
| Target Tracking | Policy type | Based on metrics |
| Step Scaling | Policy type | Not recommended by AWS |
| Scheduled Scaling | Time based | Based on date and time |
Terraform Resource Registration for Application Auto Scaling
Registering the service with Application Auto Scaling is the first required step.
The resource awsappautoscalingtarget registers the ECS service for autoscaling.
The configuration requires maxcapacity, mincapacity, resourceid, scalabledimension, and service_namespace.
An example configuration uses maxcapacity 10, mincapacity 1, resourceid service/my-cluster/my-service, scalabledimension ecs:service:DesiredCount, service_namespace ecs.
The impact of correct registration is that the Application Auto Scaling service can discover the resource and enforce scaling limits. Without registration the policy has no target to act upon and scaling actions are rejected.
The contextual layer connects this registration to the ECS service resource. The ECS service resource must exist with a stable name and cluster reference so the resourceid string matches the actual service. The resourceid pattern service/my-cluster/my-service must align with the cluster name and service name used in awsecsservice.
Target Tracking and Step Scaling Policy Configuration
Target tracking is the best default. Set a CPU or request count target and let AWS handle the math.
Use step scaling for more control over scaling speed at different thresholds.
Use scheduled scaling for predictable traffic patterns.
Combine all three for the most responsive setup.
A target tracking policy configuration includes target_value and a customized metric specification.
An example policy uses name cpu-policy, policytype TargetTrackingScaling, resourceid from the autoscaling target, scalabledimension from the target, servicenamespace from the target, and targettrackingscalingpolicyconfiguration with target_value 50.
The customized metric specification includes metric_name CPUUtilization, namespace AWS/ECS, statistic.
The impact of target tracking is automatic proportional adjustments without manual step definitions. The system calculates the required task count to maintain the target utilization.
The contextual layer connects the targetvalue to the real world workload. A targetvalue of 50 means the system aims to keep CPU utilization near 50 percent. A higher target reduces task count and cost but increases risk of saturation. A lower target increases headroom.
IAM Role Prerequisites for Autoscaling
First of all, you need a role with a policy to handle the autoscaling via the service application-autoscaling.amazonaws.com.
This means you permit the autoscaling service to adjust the desired count of your ECS Service based on Cloudwatch metrics.
The IAM role is required because Application Auto Scaling must assume a role to call ECS APIs on behalf of the user. Without the role, scaling actions fail with access denied errors.
The contextual layer links the IAM role to the provider configuration and module composition. The role is typically created in an IAM module and passed to the ECS module and auto scaling module.
Lifecycle Ignore Changes for Desired Count
Without this, every terraform apply would reset the task count to whatever is in your Terraform config, overriding the auto scaler's adjustments.
The required configuration is:
lifecycle {
ignore_changes = [desired_count]
}
This lifecycle meta argument prevents Terraform from reverting the desired_count back to the value declared in the configuration after Application Auto Scaling changes it.
The impact is preservation of autoscaling autonomy. Terraform continues to manage the service definition but relinquishes control of the dynamic desired count.
The contextual layer connects this to the autoscale block inside awsecsservice which defines mincapacity and maxcapacity. Those values set bounds but do not control the live count.
Threshold Selection Guidelines
Choosing Scaling Thresholds depends on the application, but guidelines exist.
CPU target tracking at 70% leaves headroom for traffic spikes while still using resources efficiently.
Scale-out cooldown of 60 seconds lets you respond quickly to growing demand.
Scale-in cooldown of 300 seconds prevents premature scale-in during temporary dips.
Always keep minimum tasks >= 2 for availability across AZs.
Use ALBRequestCountPerTarget for web services. It responds to load before CPU saturates.
These guidelines provide practical defaults that balance responsiveness and stability.
The impact of a 70% CPU target is buffer for bursts. The impact of a 60 second scale-out cooldown is faster reaction to load increases. The impact of a 300 second scale-in cooldown is avoidance of flapping.
The contextual layer ties these thresholds to the targettrackingscalingpolicyconfiguration. The target_value can be set to 70 instead of 50 to follow the guideline.
Module Composition and Variable Patterns
A Terraform project can be organized into modules for vpc, elb, iam, ecs, auto_scaling, and route53.
Variables are defined in terraform/variables.tf.
An example variable block:
variable "region" {
default = "eu-west-1"
type = string
description = "The region you want to deploy the infrastructure in"
}
Another variable:
variable "hosted_zone_id" {
type = string
description = "The id of the hosted zone of the Route 53 domain you want to use"
}
The main.tf references modules with outputs passed as inputs.
Example module references:
provider "aws" {
version = "~> 3.0"
region = var.region
}
module "vpc" {
source = "./modules/vpc"
}
module "elb" {
source = "./modules/elb"
hosted_zone_id = var.hosted_zone_id
load_balancer_sg = module.vpc.load_balancer_sg
load_balancer_subnet_a = module.vpc.load_balancer_subnet_a
load_balancer_subnet_b = module.vpc.load_balancer_subnet_b
load_balancer_subnet_c = module.vpc.load_balancer_subnet_c
vpc = module.vpc.vpc
}
module "iam" {
source = "./modules/iam"
elb = module.elb.elb
}
module "ecs" {
source = "./modules/ecs"
ecs_role = module.iam.ecs_role
ecs_sg = module.vpc.ecs_sg
ecs_subnet_a = module.vpc.ecs_subnet_a
ecs_subnet_b = module.vpc.ecs_subnet_b
ecs_subnet_c = module.vpc.ecs_subnet_c
ecs_target_group = module.elb.ecs_target_group
}
module "auto_scaling" {
source = "./modules/auto-scaling"
ecs_cluster = module.ecs.ecs_cluster
ecs_service = module.ecs.ecs_service
}
module "route53" {
source = "./modules/route53"
elb = module.elb.elb
hosted_zone_id = var.hosted_zone_id
}
You can see how you can reference the outputs of one module to be used as a variable in another module.
The impact of modularization is reusability and separation of concerns. The auto_scaling module depends on outputs from the ecs module.
The contextual layer connects this pattern to the earlier resources. The ecs module outputs the cluster name and service name which are required to construct resourceid for awsappautoscaling_target.
Outputs and Observability
Outputs expose scaling metadata for downstream consumption.
Example outputs:
output "scaling_target_resource_id" {
value = aws_appautoscaling_target.ecs.resource_id
}
output "min_capacity" {
value = aws_appautoscaling_target.ecs.min_capacity
}
output "max_capacity" {
value = aws_appautoscaling_target.ecs.max_capacity
}
These outputs allow other modules or CI pipelines to read the scaling limits and resource identifier.
The impact is visibility and auditability. Teams can confirm the registered limits without reading state files.
The contextual layer ties outputs to the summary statement that ECS auto scaling in Terraform starts with awsappautoscalingtarget to register the service, then awsappautoscalingpolicy for the scaling logic.
Summary of Terraform ECS Autoscaling Workflow
ECS auto scaling in Terraform starts with awsappautoscalingtarget to register the service, then awsappautoscalingpolicy for the scaling logic.
Target tracking is the best default. Set a CPU or request count target and let AWS handle the math.
Use step scaling for more control over scaling speed at different thresholds.
Use scheduled scaling for predictable traffic patterns.
Combine all three for the most responsive setup.
And always set lifecycle { ignorechanges = [desiredcount] } on the ECS service so Terraform does not override the auto scaler.
This workflow ensures infrastructure as code manages the autoscaling configuration while runtime adjustments remain under Application Auto Scaling control.
The real-world consequence is elastic task capacity that matches demand, reduced manual intervention, and cost optimization during low usage.
The contextual layer connects all components: the ECS cluster provides the execution environment, the ECS service defines the task definition and desired count, the autoscaling target registers the service, the autoscaling policy defines the behavior, the IAM role grants permissions, the lifecycle block preserves autonomy, and module outputs provide observability.