RDS instances with zero client connections for 30 days
What does ZopNight detect here?
An RDS instance that held zero client connections at both average and peak, with CPU under 5%, across 30 days gets flagged for its full monthly bill. ZopNight skips read replicas, Multi-AZ standbys, stopped instances and scheduled databases, and abstains whenever the connection or CPU series is missing.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-169 |
| Category | idle |
| Severity | high |
| Metric | none — pure configuration read |
| Source | rds_idle.go |
Where it applies
Zero connections is necessary, not sufficient
DatabaseConnections counts client sessions and nothing else. A database can sit at zero
client sessions while it applies replicated changes or grinds through a nightly batch job, and
stopping that database would break something real. So the rule demands a second axis:
CPUUtilization must be measured, and both its average and its peak must stay under 5%. When
the CPU series is absent from CloudWatch the rule abstains. Single-axis evidence is too thin
for a finding whose end state is deleting a database.
The connection test itself has no tolerance band. Any non-zero average or maximum on
DatabaseConnections means the instance is in use, and RDS publishes around 20 CloudWatch metrics per
instance, so the rule reads the connection series by its exact name rather than taking whatever
metric happens to come back first for the resource.
Which databases never get flagged
Four exclusions run before any metric is read:
- Read replicas and Multi-AZ standbys: both legitimately carry zero application connections while doing replication or failover duty. Cross-region replicas and Multi-AZ members are recognised from discovery metadata; a same-region replica flag is still a known gap in the producer.
- Instances that are not in the
availablestate: an already-stopped database burns no compute, so an “idle, stop it” finding would be a no-op. - Databases on a known recurring schedule. A database parked off-hours reads as zero connections at night precisely because a schedule is already optimising it.
Why the idle gate reads the full series
The 30-day window in the finding text is a display choice. The idle decision runs on the complete harvested series first: an instance that had traffic six weeks ago and went quiet in the trailing month is not called idle. Trimming the series before the gate would have manufactured false delete recommendations for recently retired workloads.
Pull both series from CloudWatch
aws cloudwatch get-metric-statistics \ --namespace AWS/RDS --metric-name DatabaseConnections \ --dimensions Name=DBInstanceIdentifier,Value=my-database \ --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 Average MaximumRun it again with --metric-name CPUUtilization. The finding requires flat connections and
CPU under 5% on both statistics.
Stopping versus deleting the instance
The savings figure assumes deletion, so it is the full monthly bill. Stopping recovers compute only: storage, provisioned IOPS and backup charges carry on at their normal rates, and AWS automatically restarts a stopped instance after 7 days. Take a final snapshot before either action. If no priced cost is available for the instance, the rule reports nothing rather than a $0 finding.