S3 Incomplete Multipart Uploads Accumulating
What does ZopNight detect here?
Incomplete multipart uploads left in S3 buckets without an abort lifecycle rule keep billing invisible part storage. ZopNight requires a measured incomplete_multipart_count above 0 as evidence, but abstains on every bucket today: the wasted-bytes figure needs paid Storage Lens Advanced metrics or an O(uploads×parts) scan, so no cheap producer exists.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-074 |
| Category | orphan |
| Severity | low |
| Metric | none — pure configuration read |
| Source | s3_multipart_cleanup.go |
Where it applies
Measured abandoned uploads, not a missing rule
- Metadata[“multipart_abort_rule_present”] (JSON bool) must be false; the prior abort_incomplete_multipart tag-absence-as-proof gate is replaced; abstains when the key is absent (lifecycle config unreadable).
- Metadata[“incomplete_multipart_count”] > 0 (evidence gate, audit 2026-06-26: config-absence alone is not evidence of waste; an explicit 0 means “measured, none found”).
- PricingAware: per-resource monthly cost, used only as the pricing-available applicability gate and never as the saving (using the whole-bucket cost overstated ~100×, the EV-T0043 bug).
- SKURatesAware: standardstorage per-GiB-HOUR rate (PRODUCER-GAP: not yet ingested → LookupSKURate returns 0 → abstain).
- PRODUCER-GAP (PERMANENT v1-abstain) incomplete_multipart_bytes: has no cheap per-bucket producer and is intentionally not wired; the only sources are per-upload S3 ListParts (the O(uploads×parts) fan-out the discoverer deliberately avoids) or the Storage-Lens ADVANCED IncompleteMultipartUploadStorageBytes metric (paid, opt-in, off by default). metadataFloatS3Multipart returns ok=false, so the rule always abstains on the saving dimension.
Why the wasted bytes cannot be measured cheaply
concrete-or-abstain (cost-driven “orphan”). The intended saving is wastedGiB × the StandardStorage per-GiB-HOUR rate × 730 (the per-GiB-HOUR rate ×730 → monthly, mirroring GCP RC-147; CurrentCostUSD=SavingsUSD, OptimizedCostUSD=0). The prior code emitted SavingsUSD=0/100%-of-bucket-cost fabrications; now the rule emits a rec only when both the wasted-bytes producer signal and the StandardStorage rate are present. Because incomplete_multipart_bytes is a PERMANENT v1-abstain (no cheap per-bucket producer) and standardstorage is not yet ingested, the rule currently abstains (returns nil) on every bucket and never emits a $0/fabricated cost rec.
Adding a 7-day abort rule
- Go to S3 Console → Select bucket → Management
- Create lifecycle rule
- Check ‘Clean up expired object delete markers’
- Check ‘Clean up incomplete multipart uploads’ after 7 days
No metrics, just the standard storage rate
None (SKURatesAware: standardstorage per-GiB-HOUR rate)