CloudWatch alarms stuck in INSUFFICIENT_DATA after their resource is gone
What does ZopNight detect here?
ZopNight flags a CloudWatch alarm only when its state has sat in INSUFFICIENT_DATA and the discoverer has affirmatively confirmed the monitored resource is gone, corroborated by a 30-day no-data window. Because that source-gone signal is not produced yet, the rule deliberately reports zero findings today rather than recommend deleting live autoscaling alarms.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-176 |
| Category | orphan |
| Severity | low |
| Metric | none — pure configuration read |
| Source | cloudwatch_alarm_unused.go |
Where it applies
INSUFFICIENT_DATA is a symptom, not a verdict
An alarm enters INSUFFICIENT_DATA when the metric it watches stops reporting. That often means
the monitored resource was deleted (an instance terminated months ago, a namespace renamed),
and the alarm is now billing for nothing. But the same state also shows up transiently: a
freshly created alarm, or a metric that paused briefly, looks identical. So the state alone is
never enough. The rule reads the real alarm state from the discoverer (the lowercased
StateValue lands in the resource status) and then demands more evidence before it will
suggest deleting anything.
The autoscaling alarm trap
The single biggest false positive this rule has ever produced: alarms that are the trigger arm of an Auto Scaling policy. When an ASG is scaled to zero, its instances stop emitting metrics, so its ScaleUp and ScaleDown alarms sit in INSUFFICIENT_DATA while being completely wired into live autoscaling. Deleting one breaks scale-up. In an earlier audit, 791 of 791 candidate findings were exactly this shape. The rule now fails closed on any alarm whose name contains scaleup, scaledown or alarmscale, or whose alarm actions point at an autoscaling policy ARN.
Why the rule reports nothing today
Firing requires an authoritative source-gone confirmation: a source_gone,
alarm_source_missing or target_resource_exists=false marker stamped by the discoverer. The
discoverer currently stamps only orphanSince (the timestamp used for the 30-day sustained
no-data corroboration), none of the three confirmation signals. So the gate is always false and
RC-176 emits zero recommendations on live data. That is intentional: age alone must never drive
a destructive delete. When pricing is available and all gates pass, the finding reports the
alarm’s full monthly charge under CloudWatch’s per-alarm rate as recoverable; without a real cost it abstains.
Listing your no-data alarms
aws cloudwatch describe-alarms --state-value INSUFFICIENT_DATA \ --query 'MetricAlarms[].[AlarmName,StateUpdatedTimestamp,Namespace]' --output tableCross-check each name against your Auto Scaling policies before drawing conclusions. The scaling alarms in this list are healthy.
Deleting an alarm safely
Confirm the monitored resource is really gone, not renamed. If the metric namespace or dimensions changed, updating the alarm is the fix; deletion is only right when nothing will ever publish that metric again.