Skip to main content
advisory · aws

ECS clusters with no services, no tasks, and no registered instances

resource types
1
rule IDs covered
1
severity
low

What does ZopNight detect here?

An ECS cluster object is free, so ZopNight reports an empty one at $0, but only after 4 counters all read zero: active services, running tasks, pending tasks, and registered container instances. That last axis is what stops the "default" cluster with idle EC2s attached from being called empty.

Signal and threshold

How ZopNight evaluates ECS clusters with no services, no tasks, and no registered instances.
Field Value
Rule IDsRC-1504
Categoryadvisory
Severitylow
Metricnone — pure configuration read
Sourceecs_cluster_empty.go

Four zeros, because three lie

Services, running tasks, pending tasks: a cluster can have all three at zero and still not be empty in the way that matters. The classic case is the default cluster with EC2 container instances registered and idling. Their cost is real, but it belongs to the EC2 instances, not the cluster object, and deleting the cluster would strand rather than save. So the rule reads a fourth counter, registered container instances, and requires all four axes present and zero before firing. Any missing counter abstains; emptiness is asserted only on complete evidence.

Why the finding is worth exactly nothing

The cluster object is free in every billing sense: the aggregator classifies it as having no cost of its own, with all real spend carried by child resources. An earlier version gated on a positive cluster cost that could never exist, which made the rule a permanent zombie that never fired at all. The fix was honesty in the other direction: fire on the real all-zeros signal, attach an explicit $0, and let the value be the cleanup action. An empty cluster’s cost is cognitive: one more object in every list, one more “wait, is this used?” in every audit.

Count the four axes yourself

Terminal window
aws ecs describe-clusters --clusters my-cluster \
--query 'clusters[].[clusterName,activeServicesCount,runningTasksCount,pendingTasksCount,registeredContainerInstancesCount]' \
--output table

Four zeros across the row reproduces the finding.

Before deleting

Empty now is not never-used: check whether CI/CD pipelines or task-run scripts reference the cluster by name, because aws ecs run-task against a deleted cluster fails at the next deploy, not today. Capacity providers attached to the cluster deserve a look too, since an auto-scaling group left behind by one can hold real cost. Deletion itself is a single call with nothing to drain, which is the pleasant consequence of only ever firing on genuinely empty clusters.

The recurring source

Empty clusters accumulate from tutorials, abandoned experiments, and IaC stacks whose destroy step failed halfway. If the same names keep reappearing, the fix is upstream in whichever pipeline creates clusters per-branch or per-experiment without a matching teardown.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·