TL;DR: S3 Inventory answers "what is actually in this bucket?" — a scheduled (daily/weekly) report of every object with size, last-modified, storage class, encryption status, and more, delivered as CSV or Parquet you can query with Athena. At $0.0025 per 1,000 objects it costs pennies, and it's the manifest source for Batch Operations. You can't optimize what you can't list.
The numbers
- Cost: $0.0025 per 1,000 objects listed — a million-object bucket reports for $2.50
- Field-tested finds from the source workflow: 12,000 orphaned profile pictures (objects with no DB row); 400+ duplicate log files found by matching ETags; an inherited 15-bucket estate cut from $140/month to $22 (~$1,400/year) after one inventory pass showed 11 buckets were dead weight
- Compliance answer in a report: "97% encrypted, 3% not" — with the exact keys to fix
Do this
-
Configure it on your biggest (or most mysterious) buckets: console → bucket → Management → Inventory configurations, or
put-bucket-inventory-configuration. Choose Parquet if there's any chance you'll query it; include size, last-modified, storage class, encryption status, and (on versioned buckets) current-versions-only. -
Wait for the first report (up to 48 h daily / 7 days weekly), then point Athena at the destination and ask the questions that have been bothering you:
SELECT key, size, last_modified_date FROM s3_inventory WHERE size > 104857600 AND last_modified_date < date_add('year', -1, now()) ORDER BY size DESC;Instant cleanup hit list: big, old, forgotten.
-
Cross-reference against your app database for orphan detection — S3 keys with no corresponding row are pure waste.
-
Feed the results into action: Batch Operations consumes inventory manifests directly for the one-time cleanup; lifecycle policies prevent re-accumulation. The mature loop is inventory → Athena filter → batch job → Slack report.
Gotchas
- Don't point the destination inside the source scope — the next report inventories the previous reports, recursively.
- Keep the destination in the same region (cross-region delivery bills transfer fees) and lock it down — inventory metadata (filenames, encryption flags) is sensitive.
- Versioned buckets bloat reports unless you select current-versions-only.
- Expire old reports with a lifecycle rule on the destination (90 days is plenty) — hoarding weekly reports from 2022 is its own little waste stream.
- Reports are snapshots, not real-time — eventually consistent, on a schedule. Event-driven work belongs to S3 Notifications.
Skip this if
- The bucket is small enough to eyeball in the console.
- You only need aggregate metrics (total size, class distribution) — that's Storage Lens, no per-object listing needed. Lens spots the what; Inventory gets you the list.