This finding is distinct from the other S3 lifecycle findings Parsivex surfaces:
- S3 wrong storage class — the bucket has no lifecycle rules and enough stored data that transitioning to a cheaper storage class (for example Intelligent-Tiering) would save money. It applies to large buckets regardless of versioning status.
- S3 incomplete multipart uploads — abandoned multipart uploads are accumulating because there is no abort rule. The bucket may already have other lifecycle rules.
- Missing lifecycle policy (this page) — the bucket has versioning enabled or suspended but zero lifecycle rules, so noncurrent object versions can accumulate indefinitely with no automatic expiration or tier transition.
A single bucket can appear in more than one of these findings when multiple conditions apply.
What triggers this finding
A versioned or growing S3 bucket with no lifecycle rules configured to manage storage costs.
Typical fix
Add lifecycle rules to expire noncurrent versions, transition objects to cheaper tiers, or clean up incomplete uploads.
Example savings
Varies by bucket size and access patterns — often $5–$100+/month on buckets with versioning enabled.
See also: Severity and savings estimates for how Parsivex calculates figures on your report.
What versioning does to a storage bill
In a versioned bucket, every version of an object is a separate billable object. Overwriting a 1 GB file ten times leaves eleven full copies on the bill, not one — S3 stores complete objects per version, not deltas. Deleting the object does not help either: S3 writes a delete marker, the object disappears from listings, and every previous version keeps billing exactly as before. That combination is what makes versioned buckets grow quietly. Nothing in the console's object view shows the versions, and the bucket looks the size the current objects say it is.
Suspending versioning stops new versions from being created but removes nothing that already exists, which is why Parsivex treats Enabled and Suspended buckets identically. The finding also requires the bucket to be at least 30 days old and to have zero lifecycle rules of any kind.
There is no size floor on this finding, and the savings figure deserves a caveat. Where a size figure is available, Parsivex reports the bucket's entire Standard-rate storage cost — it cannot see the split between current and noncurrent versions without an object inventory, so the number is an upper bound on what expiring old versions could return, not a prediction. Where no size figure is available, the estimate is reported as $0 rather than guessed.
Measuring noncurrent versions
Confirm the versioning state first — an absent Status field means versioning was never enabled:
aws s3api get-bucket-versioning --bucket build-artifacts
For the actual split, S3 Storage Lens is the cheapest answer: its free tier reports noncurrent version bytes per bucket without you paying to list anything. For a quick sample on a smaller bucket, list-object-versions answers directly:
aws s3api list-object-versions --bucket build-artifacts --max-items 1000 \
--query '{Current: length(Versions[?IsLatest == `true`]), Noncurrent: length(Versions[?IsLatest == `false`]), Markers: length(DeleteMarkers)}'
On a large bucket, stop and set up an S3 Inventory report instead — a paginated version listing of a multi-million-object bucket is billed per request and can cost more than the versions themselves.
Buckets that should keep every version
- Object Lock in compliance mode. Locked versions cannot be deleted by anyone, including a lifecycle rule, until their retention period expires. An expiration rule on such a bucket does nothing at all and quietly gives you a false sense of housekeeping.
- Regulated or contractual retention. Versioning is often the mechanism implementing a records policy. Expiring noncurrent versions there is a compliance incident that happens to save $8 a month.
- Replication sources. Cross-Region and Same-Region Replication require versioning, and replication status is tracked per version. Aggressive expiration on the source can remove versions before they replicate.
- Buckets protecting against ransomware or accidental deletion. Version history is the recovery mechanism; the cost is the premium.
- Small buckets. With no size floor on this finding, a 40 MB versioned bucket can appear on your report over a few cents a month. Judge it by the dollar figure, not by its presence in the list.
Expiration is permanent
NoncurrentVersionExpiration deletes data, and deleted versions do not come back. There is no recycle bin, no undo, and no way to reconstruct a version once the rule has run. Whatever retention window you pick becomes the maximum distance you can ever roll an object back.
Two rule shapes make the change safer:
- Transition before expiring.
NoncurrentVersionTransitionmoves old versions to a cheaper class while keeping them retrievable. Most of the saving, none of the loss. - Keep a floor.
NewerNoncurrentVersionsretains the N most recent noncurrent versions regardless of age, so a rapidly-overwritten object still has recent history even under a short window.
Start with a long window — 90 or 180 days — confirm from the next month's bill that the rule is doing what you expect, and tighten from there. Lifecycle deletions are evaluated daily and can lag by a day or more after the rule is saved, and S3 does not charge for the deletes themselves. One operational note: writing a rule replaces the bucket's whole lifecycle configuration, so fetch the existing rules and merge yours into them before saving rather than submitting your new rule alone.