S3 Noncurrent Version Accumulation
What does ZopNight detect here?
Versioned S3 buckets with no noncurrent-expiry lifecycle rule accumulate stale object copies at full STANDARD rates. ZopNight would price savings as noncurrent GB times the per-GB-hour STANDARD rate times 730, but abstains today. No producer writes noncurrent_version_bytes_gb yet, since CloudWatch BucketSizeBytes cannot split current from noncurrent storage.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-073 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | s3_versioning.go |
Where it applies
Versioning on with no noncurrent cleanup rule
- Metadata[“versioning_enabled”] (JSON bool) must be true (authoritative discoverer flag, replaces the old customer versioning=enabled tag).
- Metadata[“noncurrent_cleanup”] (JSON bool): abstains when true (a lifecycle rule that expires noncurrent versions already exists); gates on this purpose-built flag, not the coarse lifecycle_policy_present.
- PRODUCER-GAP Metadata[“noncurrent_version_bytes_gb”] (per-bucket GB of noncurrent object versions, from S3 Storage Lens advanced metrics / an S3 Inventory report; CloudWatch’s BucketSizeBytes cannot split current vs noncurrent). No producer writes this key yet, so the rule abstains until it lands.
Expiring old versions removes the storage outright
concrete-or-abstain (cost-driven rightsizing). savings = noncurrentGB × LookupSKURate(STANDARD) × hoursPerMonth. The STANDARD rate is per-GB-hour (the catalogued per-GB-month figure ÷ 730 at ingest, per pricing/aws/stream.go isStorageRate), so the ×730 is mandatory to get a monthly figure (omitting it under-reports ~730× and the rec is swallowed by the $5 floor; same trap as GCP RC-147). Expiring the noncurrent versions removes that STANDARD storage entirely (full rate, not a tier-transition delta). Abstains (returns nil) when noncurrent_version_bytes_gb is absent (the current live state), the STANDARD rate is missing, or the saving is non-positive. Never the prior $3.0/mo fixed estimate, never the old governance $0-advisory cost-dodge (the rule no longer hides under a non-cost-driven category to ship a SavingsUSD=0 rec). Mirrors sibling RC-072.
Expiring noncurrent versions after 30 days
- Go to S3 Console → Select bucket → Management
- Create a lifecycle rule that expires noncurrent versions after 30 days
- Limit the number of noncurrent versions to keep
- This prevents unlimited version accumulation and reclaims the stale-copy storage
No metrics, just the Standard per-GB rate
None (SKURatesAware: STANDARD per-GB-hour rate)