ECS services with a repeating weekly idle window worth scheduling around
What does ZopNight detect here?
Usage heatmaps built from a service's CPU and memory reveal repeating idle windows (nights, weekends), and ZopNight converts the measured idle fraction directly into the saving: a service idle 60% of the week saves 60% of its compute. Applying the schedule sets desired count to 0 on that cron automatically.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-046 |
| Category | schedule |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | ecs_heatmap_schedule.go |
Where it applies
From heatmap to cron
The aggregator builds each service a weekly activity heatmap from both the CPU and memory series ECS emits. Two axes mean a memory-resident but CPU-quiet workload still reads as busy. When the map shows a repeating idle window, it yields a concrete start/stop cron pair and a measured idle percentage, and that percentage times the service’s measured monthly cost is the saving, because Fargate and EC2 capacity is charged only while tasks run. Nothing is assumed about your working hours; a service idle Tuesday afternoons saves Tuesday afternoons.
Genuinely actionable, not advisory
ECS services are in ZopNight’s schedulable set: applying this recommendation has the executor drive the service’s desired count to zero and back on the recommended cron. That distinguishes it from schedule findings on resources with no native off switch: here the lever is a supported operation, reversible by editing or deleting the schedule.
The fences around it
Production services never fire. A prod-pattern name or environment tag vetoes before any math, because a forced off-hours stop of production is an outage wearing a savings badge. Services idle 95% of the week or more also abstain: that shape is not a schedule candidate but a scale-to-zero candidate, owned by the running-idle rule, and emitting a schedule there would claim near-total savings for keeping a nearly-dead service on a timer. No heatmap, no cron pair, or no priced cost each abstain as well.
Look at the shape yourself
aws cloudwatch get-metric-statistics \ --namespace AWS/ECS --metric-name CPUUtilization \ --dimensions Name=ClusterName,Value=my-cluster Name=ServiceName,Value=my-service \ --start-time "$(date -u -v-14d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 3600 --statistics AverageHourly resolution over two weeks shows the weekly rhythm the heatmap formalizes.
What to verify before enabling
Scheduled scale-to-zero interacts with everything that assumes the service exists at night: cron jobs that call it, monitors that alert on its absence, deploy pipelines that roll at 2 a.m. Walk those first, then enable the schedule and let the first week run with someone watching. Tasks stopped on schedule restart clean the next morning; the risk is never the mechanism, it is the dependency nobody listed.