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:
-
Delete the bucket — if the data is no longer needed, this eliminates the storage cost entirely.
-
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.
-
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
-
Deleting a general purpose bucket — AWS S3 User Guide
-
Emptying a bucket — AWS S3 User Guide
-
Deleting object versions from a versioning-enabled bucket — AWS S3 User Guide
-
Managing the lifecycle of objects — AWS S3 User Guide
-
Using S3 Object Lock — AWS S3 User Guide
-
Monitoring metrics with Amazon CloudWatch — the BucketSizeBytes and NumberOfObjects metrics used in the report charts
-
Assessing storage activity with S3 Storage Lens — AWS S3 User Guide
Bill Gleeson
Comments