ECS services scaled to zero desired and zero running tasks
What does ZopNight detect here?
ZopNight flags an Amazon ECS service whose `desiredCount` and `runningCount` are both 0, as returned by `ecs:DescribeServices`. A service definition with no tasks costs nothing, so the finding is a $0 cleanup advisory rather than a saving; it asks you to confirm the service is abandoned and then remove it with its target groups and load balancers.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-044 |
| Category | advisory |
| Severity | medium |
| Metric | none — pure configuration read |
| Threshold | desiredCount = 0 and runningCount = 0 |
| Source | ZopNight |
| Permissions used | ecs:ListClusters · ecs:ListServices · ecs:DescribeServices |
Where it applies
A service with no tasks left running
An ECS service keeps a desired number of tasks alive. When someone sets that number to zero, the tasks stop and so does their compute bill: ECS pricing has no charge for orchestration, and Fargate bills vCPU and memory only while a task runs. What remains is the service definition plus anything wired to it, such as a load balancer target group, service discovery entries and alarms. Those leftovers are where the confusion and some of the cost live.
Finding zero-task services in a cluster
describe-services returns desiredCount, runningCount and pendingCount for each service.
This lists the ones scaled to nothing:
CLUSTER=my-clusteraws ecs describe-services --cluster "$CLUSTER" \ --services $(aws ecs list-services --cluster "$CLUSTER" --query 'serviceArns[]' --output text) \ --query 'services[?desiredCount==`0` && runningCount==`0`].[serviceName,status,createdAt]' \ --output tabledescribe-services accepts up to 10 services per call, so page through larger clusters.
Both counts must be an explicit zero
ZopNight reads the desired and running task counts it collected for the service. It fires only when both are present and both are zero. A service with a desired count of zero that still has a task draining, or one that wants tasks but cannot place them, does not match.
When the service is skipped
If the task counts were not collected for a service, the rule makes no guess and raises nothing. It
also stays silent when the service is on a recurring ZopNight schedule that parks it off-hours, and
when ZopNight’s uptime record shows the service running less than 5% of the time (once suppressed,
it stays quiet until uptime passes 8%). In practice, a service that has sat at zero tasks for 95% or more
of the measured window is not reported; the finding surfaces services scaled to zero recently, or
ones whose uptime ZopNight has not measured. The describe-services command above lists the
long-idle ones. A
service that is still running tasks but receiving no traffic is a different problem, covered by
Running ECS Service Idle (No Traffic).
Why the finding shows $0
The service object is free and its tasks already cost nothing, so current cost, optimized cost and saving are all $0. Earlier versions of this check claimed the whole resource cost as a saving, which could not be backed by evidence. Any real money sits in attached resources, such as a load balancer that now routes to an empty target group, and those are priced by their own rules.
Cleaning up an abandoned service
- Confirm with the owning team that the service is not parked on purpose by a scheduler or a deployment pipeline.
- Check that no scheduled task, EventBridge rule or other service depends on it.
- Delete it:
aws ecs delete-service --cluster CLUSTER --service SERVICE. With zero tasks the--forceflag is not needed. - Remove the target groups, listener rules and load balancer that served it if nothing else uses them.