S3 noncurrent versions with no lifecycle rule: How to Find Them and What They Cost
S3 noncurrent versions with no lifecycle rule are every previous version of every object, retained forever because versioning was enabled without an expiry policy. They are one of the most reliable sources of pure waste in an AWS account, because nothing in the console flags them and nothing fails when they exist — the bill simply stays higher than it needs to be.
This page covers what they cost, the command that lists yours, and — importantly — what to check before deleting anything.
What they are and why they linger
Versioning protects against accidental deletion and overwrite by keeping every previous version of an object. It is genuinely valuable — it is the main defence against a script that overwrites the wrong prefix, and against ransomware.
It is also unbounded by default. Enabling versioning without a lifecycle rule means every version of every object is retained forever and billed forever. A file overwritten hourly accumulates 8,760 billable versions a year.
Deletes make it worse rather than better. Deleting an object in a versioned bucket writes a delete marker and retains the data. Storage goes up when you delete things.
What they cost
A bucket holding 100 GB of current objects that are rewritten daily accumulates roughly 3 TB of noncurrent versions in a year — about $70 a month at Standard rates, rising every month it continues.
This and incomplete multipart uploads are the two reasons a bucket’s billed size exceeds the size of what you can see in it.
Finding yours
# Is versioning on, and is there a lifecycle rule?
aws s3api get-bucket-versioning --bucket my-bucket
aws s3api get-bucket-lifecycle-configuration --bucket my-bucket 2>&1 | head -20
# Buckets with versioning enabled and no lifecycle configuration at all.
for b in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do
v=$(aws s3api get-bucket-versioning --bucket "$b" --query Status --output text 2>/dev/null)
if [ "$v" = "Enabled" ]; then
if ! aws s3api get-bucket-lifecycle-configuration --bucket "$b" >/dev/null 2>&1; then
echo "$b: versioning ON, no lifecycle rule"
fi
fi
done
For a size breakdown by version status, S3 Storage Lens is the right tool — it reports current versions, noncurrent versions, and delete markers separately, which nothing else does without enumerating the bucket.
Before you delete
Noncurrent versions are your recovery path. Expiring them at 7 days means a mistake discovered on day 8 is unrecoverable. Choose the retention period from how long it realistically takes to notice a bad overwrite — 30 to 90 days is a common landing point, and compliance may set a floor.
Transitioning to a cheaper storage class is often better than expiring: noncurrent versions moved to Glacier Instant Retrieval cost a fraction of Standard while remaining immediately restorable.
Stopping them coming back
Pair every put-bucket-versioning with a lifecycle rule, in the same module:
{
"Rules": [{
"ID": "expire-noncurrent-versions",
"Status": "Enabled",
"Filter": {},
"NoncurrentVersionTransitions": [
{ "NoncurrentDays": 30, "StorageClass": "GLACIER_IR" }
],
"NoncurrentVersionExpiration": { "NoncurrentDays": 180, "NewerNoncurrentVersions": 3 },
"Expiration": { "ExpiredObjectDeleteMarker": true }
}]
}
NewerNoncurrentVersions keeps a floor of recent versions regardless of age, which is the safety valve that makes an aggressive day count acceptable.
Related
- S3 incomplete multipart uploads — parts of failed large uploads, billed as storage and invisible in the console and in the bucket listing
- CloudWatch log groups that never expire — log groups created with the default retention of Never Expire, accumulating ingestion and storage charges indefinitely
- The whole cost-waste checklist — every category in this series
- NAT gateway cost calculator — model the largest recurring VPC charge
Prices quoted are us-east-1 list rates, last checked on 2026-08-22, and are shown with the arithmetic so you can substitute the rates for your own region. Always confirm against the AWS pricing page before acting on a number.