An S3 noncurrent version lifecycle policy deletes old Amazon S3 object versions, or moves them to cheaper storage, a set number of days after replacement. In a versioned Amazon S3 bucket, every overwrite and delete keeps the previous version. Each noncurrent version is billed at its storage class rate until something removes it. Apply this policy to every versioned bucket once the team confirms how long older versions are actually needed for recovery.
Policy at a Glance
Attribute | Detail |
|---|---|
Cloud Provider | AWS |
Resource Type | Amazon S3 buckets with versioning enabled |
Terraform Attribute |
|
Compliant Value | A lifecycle rule that expires or transitions noncurrent versions after a defined number of days, e.g. |
Cost Impact | Stops noncurrent versions from accumulating at S3 Standard rates indefinitely |
Why This Policy Matters
How It Helps Reduce Cloud Costs
Amazon S3 versioning keeps every prior version of an object when the object is overwritten or deleted. Each of those noncurrent versions is a full, separately billed object.
Versioning has no built-in expiry. Without a lifecycle rule, a bucket that is overwritten often keeps paying for every version it has ever stored.
This is a common source of hidden S3 spend. The S3 console shows current objects by default, so a bucket can look small while most of its billed storage sits in versions nobody sees.
An S3 noncurrent version lifecycle rule caps that growth. Noncurrent versions either expire after a set number of days or move to a cheaper storage class. Common targets are S3 Standard-IA and S3 Glacier Instant Retrieval.
Versioning still does its job. The current object is untouched, and recent versions stay available for recovery inside the window the team chooses.
Potential Savings
The savings depend on how often objects change. Buckets for build artifacts, Terraform state, data exports, and frequently rewritten datasets accumulate noncurrent versions fastest.
Consider a 10 TB bucket in US East (N. Virginia) where about 2 TB of objects are overwritten each month. S3 Standard storage is listed at about $0.023 per GB-month for the first 50 TB.
After 12 months with no lifecycle rule, the bucket holds roughly 24 TB of noncurrent versions. That is about $550 per month for data the team almost never reads, and the figure keeps rising by about $46 every month.
With a rule that expires noncurrent versions after 30 days, the same bucket holds about 2 TB of noncurrent versions at steady state. That is roughly $46 per month, regardless of how long the bucket runs.
These figures are illustrative and use list prices at the time of writing. Real savings depend on object size, change rate, and region, but the growth pattern is the same in every versioned bucket.
Implementation Guide
Infrastructure-as-Code Example (Terraform)
The following examples show a versioned Amazon S3 bucket with no lifecycle rule, and the corrected configuration.
Non-compliant configuration: versioning enabled, no noncurrent version rule
Every pipeline run that overwrites an artifact leaves the old copy behind as a noncurrent version. Nothing in this configuration ever removes it, so S3 Standard storage grows with every build.
Compliant configuration: transition, then expire noncurrent versions
This rule moves each noncurrent version to S3 Standard-IA 30 days after it is replaced. It expires noncurrent versions 90 days after they are replaced, while always keeping the three newest noncurrent versions of each object.
The empty filter {} block applies the rule to every object in the bucket. Use prefix or tag inside filter to scope the rule to part of the bucket instead.
For buckets where old versions have no recovery value, drop the transition block and keep only noncurrent_version_expiration. Deleting is cheaper than storing in any storage class.
Step-by-Step Fix Instructions
Find every versioned bucket in Terraform. Search for
aws_s3_bucket_versioningresources withstatus = "Enabled".For each versioned bucket, check whether an
aws_s3_bucket_lifecycle_configurationresource exists with anoncurrent_version_expirationornoncurrent_version_transitionblock.Confirm the recovery window with the bucket owner. Ask how far back the team has ever needed to restore a previous version, and check any compliance retention requirement.
Add or extend the bucket's
aws_s3_bucket_lifecycle_configurationwith a noncurrent version rule sized to that window.Run
terraform planand confirm the change only adds or updates the lifecycle configuration. It does not touch current objects.Apply the change. Amazon S3 runs lifecycle actions asynchronously, so expect existing noncurrent versions to be removed or transitioned over the following days.
Add Infracost to CI/CD so any new versioned bucket without a noncurrent version rule is flagged in the pull request before merge.
Best Practices
Make a noncurrent version rule a default in shared Terraform modules that enable S3 versioning. Let teams override the day count, not remove the rule.
Use
newer_noncurrent_versionsto keep a fixed number of recent versions for rollback, while expiring the long tail.Add an
expirationblock withexpired_object_delete_marker = truein the same rule set, so delete markers with no remaining versions are cleaned up too.Add
abort_incomplete_multipart_uploadwithdays_after_initiationto the same configuration, since incomplete uploads are another source of invisible S3 storage.Short retention is not right for every bucket. Buckets that protect against accidental deletion or ransomware often need a longer noncurrent window.
Tools and Scripts
How does Infracost detect missing S3 noncurrent version rules automatically?
The Amazon S3 noncurrent object version policy is available in Infracost, including in the free trial. When Infracost runs in CI/CD, it checks S3 bucket configurations in each pull request. It flags buckets with no lifecycle rule for noncurrent object versions, directly in the PR comment.
This catches the problem when the fix is a few lines in the same pull request, before the bucket starts accumulating versions. Infracost also scans existing repositories for buckets already in violation. FinOps and platform teams can then burn down that backlog over time and measure progress as the count of non-compliant buckets falls.
To check a bucket's versioning status and current lifecycle rules with the AWS CLI:
To list the noncurrent versions in a bucket, with their size in bytes:
Listing versions is slow on very large buckets. For those, S3 Storage Lens or S3 Inventory reports give the same picture without listing every object.
Examples of Impact
Illustrative example: CI artifacts in a versioned bucket. A platform team stores build artifacts in a versioned S3 bucket. Every pipeline run overwrites the same keys. After a year, almost all of the bucket's billed storage is noncurrent versions of artifacts nobody will deploy again. Adding a 30-day noncurrent version expiration rule stops that growth and removes the backlog within days.
This pattern is typical wherever automation rewrites the same object keys on a schedule.
Illustrative example: data exports kept for recovery. A data team exports daily snapshots to fixed keys and wants 90 days of history. Transitioning noncurrent versions to S3 Standard-IA after 30 days keeps the full recovery window available. Expiring them at 90 days caps the history, and most of it sits at the lower Standard-IA rate.
(These are illustrative, composite scenarios, not specific customer accounts.)
Considerations and Caveats
Expiration is permanent. Once Amazon S3 expires a noncurrent version, that version cannot be recovered. Confirm the recovery window with the bucket owner first.
Minimum storage durations apply. S3 Standard-IA bills a 30-day minimum, and S3 Glacier Instant Retrieval and Glacier Flexible Retrieval bill 90 days. Expiring versions sooner than that still incurs the minimum charge.
Small objects may not transition. By default, Amazon S3 does not transition objects smaller than 128 KB. Per-object transition requests can cost more than the storage saved.
One lifecycle configuration per bucket.
aws_s3_bucket_lifecycle_configurationmanages the bucket's whole lifecycle configuration, so all rules for one bucket belong in a single resource.Object Lock and compliance holds take priority. Versions under S3 Object Lock retention cannot be deleted by a lifecycle rule until the lock expires.
Related Policies and Concepts
Amazon S3 - consider deleting or moving old objects to a cheaper storage class: the companion Object Storage policy that applies lifecycle rules to current objects rather than noncurrent versions.
Amazon S3 - consider deleting incomplete multi-part uploads: another Object Storage policy that removes S3 storage that is billed but not visible in normal object listings.
Azure Storage Accounts - consider using a lifecycle policy for blob storage: the Azure equivalent, using lifecycle management rules to tier or delete blobs and blob versions.
Amazon ECR - consider using a lifecycle policy: a parallel policy that stops old container images from accumulating storage cost indefinitely.
Amazon CloudWatch - consider using a retention policy to reduce storage costs: the same retention principle applied to CloudWatch Logs log groups.
Frequently Asked Questions (FAQs)
Is this policy supported in Infracost?
Yes. The Amazon S3 noncurrent object version policy is supported in Infracost and available in the free trial. Infracost flags S3 buckets that have no lifecycle rule for noncurrent object versions, so the team can add one before the pull request merges.
Can this policy be customized?
Yes. Teams can adjust how Infracost enforces the Amazon S3 noncurrent object version policy, for example warning the engineer or blocking the pull request. The number of days and the target storage class are chosen by the team in Terraform, not by Infracost.
Does Infracost automatically fix violations?
No. Infracost identifies and reports S3 buckets without a noncurrent object version rule. Choosing the retention window and applying the lifecycle configuration is a decision the team makes and reviews in its own pull request.
Is this policy cloud-agnostic?
No. This policy targets Amazon S3 through the aws_s3_bucket_lifecycle_configuration Terraform resource. Azure Blob Storage and Google Cloud Storage have their own versioning and lifecycle settings, with different resource and attribute names.
How often should I review S3 noncurrent version rules?
Teams running Infracost in CI/CD get an S3 noncurrent object version check on every pull request that changes S3 bucket configuration. For existing buckets, a quarterly review of noncurrent version windows against recovery and compliance needs is a reasonable cadence.
Does deleting noncurrent versions affect the current S3 object?
No. A noncurrent version expiration rule only acts on versions that have already been replaced. The current version of each Amazon S3 object stays in place and is not changed by the rule.
Should I disable S3 versioning instead of adding a lifecycle rule?
Usually not. S3 versioning protects against accidental overwrites and deletions. A noncurrent version lifecycle rule keeps that protection for a defined window while preventing old Amazon S3 versions from accumulating cost indefinitely.
Create Free Account
This policy is supported in Infracost and available in the free trial. Sign up today and scan your code using our entire library of FinOps policies.