Your ECS capacity provider says managed scaling is on. Your ASG says otherwise.
If an ECS capacity provider has managed scaling ENABLED but its Auto Scaling group has MinSize equal to MaxSize, the cluster cannot scale out. ECS makes the scaling decision, the ASG has no headroom to grant it, and the request is silently discarded. Nothing alarms, because no component failed. Fix it by raising MaxSize above MinSize — this costs nothing, since you are billed for instances that run, not for the ceiling.
There is a particular kind of AWS misconfiguration that survives for years, and it is not the kind that shows up red on a dashboard. It is the kind where every individual component reports that it is fine, and the system as a whole cannot do the thing everyone believes it does.
Here is one we found on a production image-processing tier. It had been in place long enough that nobody remembered setting it up, and the account was already being monitored by a well-known commercial APM the whole time.
What does the misconfiguration look like?
An ECS cluster with a capacity provider attached. Open it in the console and you see this:
Capacity provider: infra-ecs-cluster-imgproxy-asg
Managed scaling: ENABLED
Target capacity: 100%
Status: ACTIVE
Everything about that says the cluster can grow. Managed scaling is on. The provider is active. If you were asked "can this tier scale out under load?" you would say yes, and you would have the screenshot to prove it.
Now open the Auto Scaling group underneath it:
Auto Scaling group: infra-ecs-cluster-imgproxy-asg
Desired capacity: 2
Minimum capacity: 2
Maximum capacity: 2
Min equals max. The group cannot add an instance. It is not permitted to.
Why is this worse than having no autoscaling at all?
If a tier has no autoscaling, everyone knows it. It is a known limitation, it gets capacity-planned, and somebody watches it during a launch.
This is different. ECS makes the scaling decision. Under load, the capacity provider evaluates target capacity, decides it needs more instances, and asks the Auto Scaling group to provide them. The ASG has no headroom, so nothing happens. The decision is made and silently discarded.
No alarm fires, because nothing failed. The capacity provider did its job. The ASG did its job — it is at its configured maximum, which is exactly where it was told to be. Every component is behaving correctly and the tier still falls over.
Meanwhile every dashboard, every architecture diagram and every runbook says the tier is protected by autoscaling. When it saturates, the first hypothesis will be wrong, because the thing everyone trusts is the thing that is broken.
Why do monitoring tools miss it?
Because it is not visible in any single resource.
Metric-based monitoring watches CPU, memory, request count. None of those are anomalous — the tier is running at its configured capacity, which is what you asked for. Config-based checks look at resources one at a time, and both of these resources are individually valid: a capacity provider with managed scaling enabled is a normal thing, and an ASG with Min=Max is a normal thing.
The defect only exists in the relationship between them. You have to hold two resources in mind at once and notice that the second contradicts the promise of the first.
That is the class of problem this whole product exists for. Not "your CPU is high" — you can see that. The things you cannot see are the ones where the configuration disagrees with itself.
How do I check my own account?
# 1. Find capacity providers with managed scaling enabled
aws ecs describe-capacity-providers \
--query 'capacityProviders[?autoScalingGroupProvider.managedScaling.status==`ENABLED`].
{name:name, asg:autoScalingGroupProvider.autoScalingGroupArn}'
# 2. For each ASG named above, check whether it can actually grow
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names <name-from-step-1> \
--query 'AutoScalingGroups[].{name:AutoScalingGroupName,min:MinSize,max:MaxSize,desired:DesiredCapacity}'
If min == max on any group that a managed-scaling capacity provider points at,
you have this.
How do I fix it, and what does it cost?
Raise MaxSize above MinSize so scaling has somewhere to go. That is the whole
fix in most cases.
Cost impact: none. You are billed for instances that run, not for the ceiling. Raising the maximum costs nothing until a real spike actually consumes the headroom — and in that moment you are paying for instances that are handling traffic you would otherwise have dropped.
If the ceiling is deliberate — a per-instance software licence, a downstream connection limit, a database that cannot take more clients — then it is a real constraint and you should keep it. But in that case:
- Write down why. A tag or a description. The next person to look at this in eighteen months will otherwise assume it is a mistake and "fix" it.
- Alarm on saturation instead. If you cannot scale out, you need to know when you are about to need to. That is a different alarm from CPU: it is "running at ceiling for N minutes".
- Turn managed scaling off. Leaving it enabled advertises a capability the infrastructure does not have, and that is the actual danger here.
The general shape
Look for anywhere a control plane makes a decision that a data plane is not permitted to carry out:
- ECS capacity provider scaling into a pinned ASG
- An Application Auto Scaling target whose min and max are equal
- A scaling policy on a group with no capacity to grow into
- A target tracking policy with no scale-out cooldown ever able to fire
In each case the request is made, the request is refused, and nothing anywhere reports a failure. The system is not lying to you. It is telling you the truth about each part, and the truth about the whole is somewhere in between.