Start a conversation

Clean Up Idle Amazon S3 Buckets

Opportunity Name

S3 Remove Idle Buckets

AWS Resource Type

Amazon S3 (buckets)

Opportunity Description

S3 buckets accumulate. They get created for a one-time data load, a temporary ETL pipeline, a proof of concept, or an application that has since been decommissioned, and then nobody deletes them. The storage charge keeps accruing every month, indefinitely, whether or not anyone ever reads the data again.


The reason these buckets survive is that AWS gives you no native signal to find them. S3 does not record a "last accessed" timestamp at the bucket level, so at any meaningful scale there is no practical way to review hundreds or thousands of buckets by hand. Without evidence that a bucket is genuinely unused, teams reasonably leave it alone.


CloudFix supplies that evidence from your Cost and Usage Report. The CUR records every billable S3 request at bucket granularity, so a bucket that carries storage charges but shows zero GET requests and zero PUT requests over the 90-day window is a bucket that nothing is reading from and nothing is writing to. CloudFix flags those buckets, quantifies the annual storage cost you are paying for them, and shows you the storage-class breakdown and object-count trend so you can confirm the finding before you act. Requiring zero PUTs as well as zero GETs is deliberate: it keeps log destinations, backup targets and other write-only buckets out of the results, since those receive Tier1 writes even when nobody reads them.

Criteria for Identifying the Opportunity

CloudFix first narrows the candidate set from your CUR, then validates each surviving bucket against the live S3 and CloudWatch APIs.


Condition

Detail

Lookback window

90 days, ending at the start of the previous day — the current day is excluded so that partial data never skews the result

Usage types considered

%TimedStorage% (storage), %Requests-Tier1 (PUT/COPY/POST/LIST), %Requests-Tier2 (GET and other read-side operations)

Line item types excluded

Tax, Credit, Refund

GET requests

Must be exactly 0 — counted as %Requests-Tier2 usage where line_item_operation = 'GetObject'

PUT requests

Must be exactly 0 — counted as %Requests-Tier1 usage

Annualized cost

Annualized amortized storage cost must exceed your tenant's resource cost threshold (default $100 per year)

Exclusion tag

Buckets tagged cloudfix:dontFixIt are dropped

Data hygiene

Rows with an empty or null resource ID or region are ignored



Other Tier2 operations — HeadObject and similar metadata calls — are counted and reported to you as "Other Requests", but they are informational only. They do not disqualify a bucket.


A Lookback Period (days) field appears in this finder's configuration, with a default of 90 and a permitted range of 30 to 90. 


Each candidate bucket must then pass the following checks, in this order. A failure at any step stops processing for that bucket and it is not reported.


Validation

Rule

IsNotObjectLocked

The bucket must not have S3 Object Lock enabled. Objects held under a retention period or legal hold cannot be removed, so the bucket cannot be reliably emptied and is excluded. If the Object Lock status cannot be determined, the bucket is rejected rather than reported.

HasChartData

CloudWatch must return a non-zero BucketSizeBytes value for at least one storage class and at least one NumberOfObjects datapoint. Buckets without CloudWatch storage metrics are skipped, so a recommendation is never shown with empty charts.

Potential Savings

Savings for this opportunity are 100% of the bucket's annualized storage cost. If you delete the bucket, the projected cost is $0.00 — there is no residual charge and no partial saving to model.


CloudFix calculates the figure directly from your CUR:


annual savings = SUM(TimedStorage cost over the 90-day window) / 90 * 365


The cost used is line_item_net_unblended_cost, falling back to line_item_unblended_cost, so the number reflects the price you actually pay after EDP and other negotiated discounts — not list price. The recommendation headlines your current annual cost, the annual saving, and the projected cost after deletion ($0.00).


What drives the number is simply how much data is sitting in the bucket and which storage class it sits in. For scale, the following illustrative figures come from the design spec for this finder, using published US East (N. Virginia) list prices. They are worked examples, not output from the finder — your own recommendations are computed from your amortized rates:


Bucket size

Storage class

Approximate annual storage cost

500 GB

S3 Infrequent Access

$77

1 TB

S3 Standard

$282

5 TB

S3 Standard

$1,411

10 TB

S3 Standard

$2,822


Buckets below your tenant's resource cost threshold (default $100 annualized) are never surfaced, so every recommendation you see clears that bar.

What Happens When the Fixer Is Executed?

Nothing is executed. This is a recommendation-only Finder — CloudFix does not ship an automated fixer for it. Bucket deletion is irreversible and destroys data, so remediation is deliberately left to you.


CloudFix produces a report containing the bucket name, region, approximate storage size, object count, average object size, GET/PUT/other request counts for the window, current annual cost, annual savings, and the storage-tier and object-count charts. You then choose one of three actions:


  1. Delete the bucket — if the data is no longer needed, this eliminates the storage cost entirely.

  2. Apply a lifecycle expiration rule — expire objects after a grace period, then delete the bucket once it is empty. This is the safer path when you want a reversal window.

  3. Dismiss the recommendation — if the bucket is still required despite having no read or write activity.


To delete manually with the AWS CLI:


# Empty the bucket first — S3 will not delete a non-empty bucket

aws s3 rm s3://YOUR-BUCKET-NAME --recursive


# Then delete the bucket itself

aws s3api delete-bucket --bucket YOUR-BUCKET-NAME --region YOUR-REGION


Before you run this, check the following:


  • Versioning. If versioning is enabled, aws s3 rm --recursive does not remove noncurrent versions or delete markers. You must delete every object version before the bucket can be removed, and those versions continue to incur storage charges until you do.

  • Object Lock. Buckets with Object Lock enabled are already excluded by the finder, but confirm no legal hold or retention setting applies to the objects.

  • Retention and compliance. Verify that no data retention obligation covers the bucket's contents.

  • Bucket ownership. Confirm with whoever owns the workload. Zero requests over 90 days is strong evidence of disuse, but it cannot detect a quarterly or annual access pattern that falls outside the window.


If you want to keep the data but stop paying Standard rates for it, consider CloudFix's S3 Intelligent-Tiering or Glacier Deep Archive opportunities instead of deletion.

Is It Possible to Roll Back Once CloudFix Implements the Fixer?

Not applicable. CloudFix does not make any change to your buckets for this opportunity, so there is nothing for CloudFix to roll back.


Be aware that the manual action itself is not reversible. Once a bucket is emptied and deleted, the objects cannot be recovered, and the bucket name is released back into the global S3 namespace where anyone can claim it. If you want a reversible path, apply a lifecycle expiration rule with a grace period rather than deleting immediately — you can remove the rule at any point before the objects expire.

Can CloudFix Implement the Fix Automatically Once I Accept the Recommendation?

No. This opportunity is recommendation-only by design. Because deleting a bucket permanently destroys data, CloudFix will not perform the deletion on your behalf under any circumstances. You must empty and delete the bucket yourself through the AWS Console, CLI, or your own infrastructure-as-code tooling after reviewing the recommendation.

Does This Fix Require Downtime?

CloudFix causes no downtime, because CloudFix makes no change.


The manual remediation carries no downtime for other AWS resources either — deleting an S3 bucket does not restart or interrupt anything else. The risk is data availability, not service availability: any client that later attempts to read from the deleted bucket will receive NoSuchBucket. That is precisely what the zero-GET, zero-PUT criteria are designed to rule out, but you should still confirm bucket ownership before deleting.


For large buckets, the deletion itself is not instantaneous. Emptying a bucket containing millions of objects can take a considerable time; a lifecycle expiration rule is generally more efficient than a recursive delete at that scale.

Additional Resources



Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. Bill Gleeson

  2. Posted

Comments