S3 Storage Tier Migration
What does ZopNight detect here?
STANDARD-dominant S3 buckets with no lifecycle policy and a measured access rate under 1,000 requests per day hold cold data at the most expensive tier. ZopNight fires on the aggregator's per-bucket STANDARD-to- STANDARD_IA delta, which is (standard rate minus IA rate) times GB times 730 hours clamped to cost. Hot or unmeasured buckets abstain.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-070 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | s3_tier_migration.go |
Where it applies
Which STANDARD buckets qualify as cold
- resource.InstanceType == STANDARD (discoverer sets InstanceType to the largest-by-bytes dominant storage class, and only STANDARD buckets are retier candidates)
- Metadata[“lifecycle_policy_present”]: skip when a policy already manages transitions
- PricingAware: per-resource monthly cost (applicability gate)
- metric: S3AccessRatePerDay, the required cold-data gate; abstains when the series is absent (S3 request metrics not enabled) or avg ≥ 1000 req/day (hot bucket; IA retrieval/request fees would erase the saving)
- injected per-bucket STANDARD→STANDARD_IA retier delta (SetS3StandardToIASavings, a dedicated S3 field, deliberately not the Azure RetierSavings map, so the two never double-count). Wired: aggregator calcS3 (cost/calc_aws_storage.go, s3RetierDeltas) sets CostOutput.S3StandardToIASavingsUSD; abstains when absent or non-positive.
Pricing the STANDARD to Standard-IA delta
concrete-or-abstain (cost-driven rightsizing). savings = (stdRate − iaRate) × stdGB × hoursPerMonth, the aggregator’s per-bucket STANDARD→STANDARD_IA retier delta, injected via SetS3StandardToIASavings (clamped to cost). The former path emitted SavingsUSD=0 under Category=“advisory” (a $0 advisory cost rec, forbidden); the prior cost*0.30 fraction is also removed. The producer chain (calcS3 CostOutput.S3StandardToIASavingsUSD → ComputedCostEntry → s3IADeltaMap → SetS3StandardToIASavings, recommender service.go) is wired end-to-end, so the rule fires concretely on a STANDARD-dominant, no-lifecycle, measured-cold bucket with a positive delta and abstains otherwise, never emitting a fraction-of-bill or $0 phantom.
Moving data to a cheaper tier
- Review S3 Storage Lens to analyze access patterns
- Enable S3 Intelligent-Tiering for automatic tier management
- For known-cold data: add lifecycle rules to transition to Standard-IA after 30 days
- For archives: choose the appropriate Glacier tier (Instant Retrieval / Flexible Retrieval / Deep Archive)
The access-rate series that gates it
S3AccessRatePerDay (aggregator metrics/aws/s3_access.go; MultiMetricsAware cold-bucket gate)