# Idle RDS Instance -- No Connections

> 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.

Source: https://zop.dev/integrations/aws/recommendations/idle-rds-instance-no-connections
Updated: 2026-08-19

---

## 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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/monitoring-cloudwatch.html), 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 `available` state**: 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

```bash
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 Maximum
```

Run 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](https://aws.amazon.com/rds/pricing/), 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.
