SNS topics with zero publishes already cost nothing
What does ZopNight detect here?
ZopNight's idle-SNS rule is retired in place and always abstains: SNS bills $0.50 per million publishes with no standing charge, so a topic with zero NumberOfMessagesPublished over 30 days already costs $0. A finding could never name a real saving, so the rule reports nothing instead of a $0 card.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-182 |
| Category | idle |
| Severity | low |
| Metric | none — pure configuration read |
| Source | sns_idle.go |
Where it applies
The publish gate and the cost gate exclude each other
The rule as originally specified had two conditions: the topic’s NumberOfMessagesPublished
series had to sit at zero on both maximum and average across a 30-day window, and the topic
had to carry a positive monthly cost. On SNS those two conditions can never be true at once.
SNS has no standing charge. Its pricing is purely per request, roughly $0.50 per million publishes, and the first million each month is free. A topic that published nothing issued no billable requests, so its cost row is either absent or $0, so the cost gate fails. A topic whose cost is positive must have had billable publishes, and the idle gate fails. No topic in any account can pass both, which means the rule was permanently unfireable in production, not merely rare.
Retired in place rather than resurrected
ZopNight’s cost rules follow a concrete-or-abstain contract: a finding filed under a cost-driven category must name a real, recoverable dollar amount, or say nothing. Deleting a topic that already bills $0 recovers $0, and there is no fallback lever: nothing to rightsize, no off-hours schedule, no commitment to re-tier. So the rule now abstains unconditionally instead of emitting a $0 card that would clutter a list people act on.
The category deliberately stays idle, the honest cost-driven label. Parking the rule under
an advisory label would have let a $0 finding sneak past the low-savings filter, the exact
shape the retirement removed.
The topic metric is still collected
The rule still declares NumberOfMessagesPublished, one of the topic-level series SNS reports to
CloudWatch, over 30 days as a required metric. That
keeps the aggregator’s fetch wiring intact: the series continues to be harvested per topic,
so anything else that reads publish activity keeps working, and a future non-cost hygiene
signal could be built on real data rather than a dead tag.
Reading publish activity yourself
aws cloudwatch get-metric-statistics \ --namespace AWS/SNS --metric-name NumberOfMessagesPublished \ --dimensions Name=TopicName,Value=my-topic \ --start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 86400 --statistics SumAn empty result or all-zero sums means nothing published in the month.
Tidying dead topics is still worthwhile
A silent topic costs nothing but can still mislead: stale subscriptions point at endpoints that no longer exist, and alarms wired to it never fire. If nothing should publish to it, review the subscription list, delete the topic, and remove any CloudWatch alarms that reference it, as hygiene, not as savings.