# S3 Noncurrent Version Accumulation

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

Source: https://zop.dev/integrations/aws/recommendations/s3-noncurrent-version-accumulation
Updated: 2026-08-19

---

## 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](https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html) 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](https://aws.amazon.com/s3/pricing/) ÷ 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

1. Go to S3 Console → Select bucket → Management
2. Create a lifecycle rule that expires noncurrent versions after 30 days
3. Limit the number of noncurrent versions to keep
4. 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)
