Dev and test RDS databases averaging 20% CPU or less that could run on a same-size db.t4g class
What does ZopNight detect here?
ZopNight picks out dev and test RDS instances on fixed-performance classes whose `CPUUtilization` averaged 20% or less over 30 days with no near-saturation peaks. Each is matched to the same-size `db.t4g` Graviton burstable class, and the finding shows the compute rate difference as the saving, only when that class is cheaper and the memory fits.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-033 |
| Category | rightsizing |
| Severity | low |
| Metric | CPUUtilization, FreeableMemory |
| Threshold | CPU avg <= 20%, peak < 80% |
| Evaluation window | 30d |
| Source | ZopNight |
| Permissions used | rds:DescribeDBInstances · cloudwatch:GetMetricStatistics |
Where it applies
Burstable classes suit databases that are mostly quiet
A fixed-performance class such as db.m5.large reserves full CPU for every hour it runs. The
burstable db.t4g classes instead earn CPU credits while idle and spend them under load. AWS’s
instance class types
page describes db.t4g as Graviton2-based and configured for Unlimited mode, which means it can burst
beyond its baseline over a 24-hour window for an additional charge. For a development or QA database
that is idle most of the day, that trade usually favours the burstable class.
Checking CPU on your own non-production databases
aws rds describe-db-instances \ --query 'DBInstances[?!starts_with(DBInstanceClass, `db.t`)].[DBInstanceIdentifier,Engine,DBInstanceClass]' \ --output table
aws cloudwatch get-metric-statistics --namespace AWS/RDS --metric-name CPUUtilization \ --dimensions Name=DBInstanceIdentifier,Value=qa-orders-db \ --start-time 2026-08-26T00:00:00Z --end-time 2026-09-25T00:00:00Z \ --period 86400 --statistics Average MaximumGates a database passes before it is flagged
- It is
availableand runs a standard RDS engine. Aurora, Neptune and DocumentDB are out, and so are Oracle and SQL Server, which the engine support table shows do not offer db.t4g. - Its name looks like dev or test (dev, test, qa, staging, sandbox, demo, nonprod, preprod or uat) and no environment tag marks it as production.
- It is not already on a
db.t*class. - Average
CPUUtilizationover the last 30 days is 20% or less, and the trusted peak is below 80%. A database that bursts close to saturation would drain its credits and is skipped. - A same-size db.t4g class exists. db.t4g stops at 2xlarge, so larger sizes have no target.
The memory check that blocks some swaps
The swap keeps the size name, not the memory. Moving a memory-optimized class such as db.r5.large
(16 GiB) to db.t4g.large (8 GiB) halves the RAM. In that case the lowest FreeableMemory seen in
the 30-day window must be larger than the memory being removed plus a 512 MiB safety margin. If
the memory of either class is unknown, the series is missing, or the headroom is not there, no
finding is raised. A missing CPU series also means no finding.
Compute savings, adjusted for hours actually run
saving = (current hourly rate - db.t4g hourly rate) x 730 x measured uptime sharecapped at monthly cost x (1 - db.t4g rate / current rate)Storage and backup charges do not change with the class, so they are left out. When uptime is unknown ZopNight assumes the database runs around the clock. No saving means no finding.
Switching the class
- Confirm the database really is non-production and nobody runs load tests on it.
- Modify the class, which causes downtime:
aws rds modify-db-instance --db-instance-identifier qa-orders-db --db-instance-class db.t4g.large --apply-immediately - Watch
CPUCreditBalancefor the first week. A balance that trends to zero means the workload is burstier than the 30 days suggested.