← All posts
2 min read

Expire noncurrent S3 versions with lifecycle

#aws#cli#s3#storage#versioning
📑 On this page

Part 50 of AWS from Zero. This lesson keeps the scope to one S3 behavior you can verify from the terminal.

What we are learning

In a versioned bucket, current-object expiration is not enough. NoncurrentVersionExpiration manages older stored versions.

Before you run it

aws sts get-caller-identity
REGION="ap-south-1"
BUCKET="replace-with-your-private-demo-bucket"

Use a private general purpose bucket that you own. Replace every placeholder before running a write or delete command.

The command

cat > lifecycle-versions.json <<'EOF'
{
  "Rules": [{
    "ID": "ExpireOldVersions",
    "Status": "Enabled",
    "Filter": {"Prefix": ""},
    "NoncurrentVersionExpiration": {
      "NoncurrentDays": 30,
      "NewerNoncurrentVersions": 3
    }
  }]
}
EOF
 
aws s3api put-bucket-lifecycle-configuration \
  --bucket "$BUCKET" \
  --lifecycle-configuration file://lifecycle-versions.json

A successful configuration command may return no output. Treat inspection as a separate required step.

Inspect the result

aws s3api get-bucket-lifecycle-configuration \
  --bucket "$BUCKET" \
  --query "Rules[].NoncurrentVersionExpiration"

Read the returned fields rather than assuming the write succeeded exactly as intended.

One tiny variation

aws s3api list-object-versions \
  --bucket "$BUCKET" \
  --query "{Versions:length(Versions),DeleteMarkers:length(DeleteMarkers)}"

Inventory current history before enabling a rule that permanently deletes old versions.

Common mistake

Noncurrent expiration is permanent. Recovery promises must align with the retention period and number of newer noncurrent versions retained.

Cleanup

aws s3api delete-bucket-lifecycle --bucket "$BUCKET"
rm lifecycle-versions.json

Removing the rule prevents future lifecycle deletion but cannot recover versions already removed.

Next, we will learn Automatically abort stale multipart uploads.

Official AWS CLI reference