Home / AWS

AWSHow-toIntermediate

Optimization: S3 storage cost with Storage Lens, Intelligent-Tiering and lifecycle rules

S3 bills grow from data nobody reads, old versions and forgotten multipart uploads. Use Storage Lens to find the big and cold buckets, pick between Intelligent-Tiering and explicit lifecycle transitions, expire noncurrent versions and incomplete uploads, and avoid small-object and minimum-duration traps.

Deepak Bhardwaj3 min read

Applies toAmazon S3 storage classes (Standard, Intelligent-Tiering, Standard-IA, One Zone-IA, Glacier Instant Retrieval, Glacier Flexible Retrieval, Glacier Deep Archive), S3 Storage Lens, lifecycle configuration

1. Find where the bytes are

S3 Storage Lens (free metrics at account/org level; advanced metrics optional) shows per bucket: total bytes, object count, % noncurrent version bytes, incomplete multipart upload bytes, and growth.

Quick per-bucket size from CloudWatch daily storage metrics:

aws cloudwatch get-metric-statistics --namespace AWS/S3 --metric-name BucketSizeBytes \
  --dimensions Name=BucketName,Value=app-exports Name=StorageType,Value=StandardStorage \
  --start-time "$(date -u -d '-2 days' +%F)" --end-time "$(date -u +%F)" --period 86400 --statistics Average

Look for: big buckets in Standard that are rarely read, buckets where noncurrent versions are a large share, and incomplete multipart bytes.

2. Intelligent-Tiering or lifecycle transitions?

Situation Choice
Access pattern unknown or changing Intelligent-Tiering: moves objects between tiers automatically by access
Known pattern (logs: hot for 30 days, then rarely read) Lifecycle transitions to IA/Glacier classes
Archive you can wait hours to read Glacier Flexible Retrieval / Deep Archive
Archive that must be read in milliseconds occasionally Glacier Instant Retrieval

Intelligent-Tiering notes: a small monthly monitoring fee per object; objects under 128 KB aren't monitored and stay in the frequent tier; no retrieval fees for the automatic tiers. Optional archive tiers need opt-in.

3. Lifecycle configuration example

{
  "Rules": [
    {
      "ID": "logs-tiering",
      "Filter": { "Prefix": "logs/" },
      "Status": "Enabled",
      "Transitions": [
        { "Days": 30,  "StorageClass": "STANDARD_IA" },
        { "Days": 90,  "StorageClass": "GLACIER_IR" },
        { "Days": 365, "StorageClass": "DEEP_ARCHIVE" }
      ],
      "Expiration": { "Days": 2555 }
    },
    {
      "ID": "versions-and-uploads",
      "Filter": {},
      "Status": "Enabled",
      "NoncurrentVersionExpiration": { "NoncurrentDays": 30, "NewerNoncurrentVersions": 3 },
      "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 },
      "Expiration": { "ExpiredObjectDeleteMarker": true }
    }
  ]
}
aws s3api put-bucket-lifecycle-configuration --bucket app-exports --lifecycle-configuration file://lifecycle.json

4. Traps

Trap Detail
Minimum storage duration IA classes 30 days, Glacier IR/Flexible 90, Deep Archive 180. Deleting earlier is charged as if stored
Minimum billable object size IA and Glacier IR bill small objects as 128 KB. Millions of tiny files can cost more after transition
Transition request charges Per-object lifecycle requests; huge counts of tiny objects make transitions expensive. Aggregate first
Retrieval fees IA and Glacier classes charge per GB retrieved; frequently read data costs more there
Versioning without expiry Every overwrite keeps a full copy forever
Replication buckets Lifecycle on the destination too, or it grows forever

Use object size filters in lifecycle rules (ObjectSizeGreaterThan) to skip tiny objects.

5. Other levers

  • Delete data nobody owns (after confirming): old build artefacts, temporary exports, test data.
  • Compress and use columnar formats (Parquet) for analytics data. Smaller and cheaper to scan.
  • S3 Express One Zone only where you need its latency; it's a different price model.
  • Request costs: chatty apps doing many LIST/GET on small objects may cost more in requests than storage.

6. Measure

Storage Lens dashboard by storage class, monthly. Expect a gradual drop as lifecycle rules run (once a day, asynchronously).

Caution

Expiration and noncurrent version expiration permanently delete data. Confirm retention with data owners, and remember Object Lock/legal holds override lifecycle deletes, which is good for compliance but confusing when you expect savings.

Checklist

  • Storage Lens reviewed for big, cold and versioned buckets
  • Intelligent-Tiering vs explicit lifecycle chosen per bucket/prefix
  • Noncurrent versions and incomplete uploads expired
  • Small-object and minimum-duration traps checked
  • Owners confirmed deletes
  • Monthly review of storage by class