# CloudWatch Log Group Standard Class -- Use Infrequent Access

> CloudWatch log groups in the Standard class with zero subscription and metric filters can move new ingestion to Infrequent Access, halving the ingest rate from $0.50 to $0.25 per GB. ZopNight measures 30-day IncomingBytes, prices savings as monthly ingested GB times the $0.25 delta, and abstains when ingestion measures zero.

Source: https://zop.dev/integrations/aws/recommendations/cloudwatch-log-group-standard-class-use-infrequent-access
Updated: 2026-08-19

---

## Standard class groups with no filters attached

- Metadata: log_class=STANDARD (provider-authoritative LogGroupClass; abstains when absent)
- Access-pattern gate: subscription_filter_count + metric_filter_count (discoverer stampLogAccessPattern); the rule fires only when both are present and zero; fail-closed on a missing probe, so IA is never recommended for a group whose real-time subscription/metric filters it would break
- Volume gate: resource.SizeGB ≥ 1, cross-checked against the harvested CWLogsStoredBytes (Maximum) so the gate still holds when SizeGB is unpopulated

## Why the discount lands on ingestion, not storage

real SKU-rate delta on the harvested ingestion volume, not a storage-rate fraction. The Standard→Infrequent-Access discount applies to *ingestion* ([$0.50 → $0.25/GB ingested](https://aws.amazon.com/cloudwatch/pricing/), exactly 50% cheaper); IA storage is the same $0.03/GB-mo as Standard, so storage contributes $0 to the saving. monthlyIngestGB is derived from CWLogsIncomingBytes normalized to a 30-day month; savings = monthlyIngestGB × ($0.50 − $0.25). The rule concrete-or-abstains: it returns nil when the ingestion series is absent or measures zero. r.pricing[resource.UID] (from SetPricing) is the aggregator's monthly cost for the log group (calcCloudWatchLogs). calcCloudWatchLogs adds an ingestion component only from cost-usage/CUR enrichment (Meta.LogIngestedGB>0), so for calculated-cost / non-billing-backed orgs it is effectively storage-only. CurrentCostUSD is reconciled onto a single consistent basis: it is max(aggregatorMonthlyCost, standardIngestionCost) where standardIngestionCost = monthlyIngestGB × $0.50. When the aggregator basis already includes ingestion (billing-backed) it dominates and is used as-is (and no second ingestion term is layered on, so the underlying AWS/Logs IncomingBytes metric is never double-counted); when it under-counts (storage-only), the rule's own measured Standard ingestion bill becomes the current-cost floor. OptimizedCostUSD = CurrentCostUSD − SavingsUSD is then strictly positive, floored at monthlyIngestGB × $0.25 (the IA rate), because a class switch trims the ingestion *rate* and cannot zero the bill. This supersedes the prior cap-to-cost (which set savings==CurrentCostUSD → OptimizedCostUSD==$0 on storage-only orgs, implying a class switch eliminated all cost; the RC-1518 defect surfaced by the 2026-07-07 da470928 audit). A defensive savings > cost cap is retained (now unreachable, since the ingestion delta is strictly below standardIngestionCost ≤ CurrentCostUSD) to match the sibling storage-delta rules. Sub-$5 savings are dropped by the central shouldDropLowSavings floor.

## Repointing the log source to a new IA group

1. Note: log class cannot be changed on existing log groups
2. Create a new log group with Infrequent Access class
3. Update the log source to write to the new log group
4. Infrequent Access supports CloudWatch Logs Insights but not real-time subscriptions

## Incoming bytes, with stored bytes as a cross-check

CWLogsIncomingBytes ([AWS/Logs IncomingBytes as CloudWatch Logs publishes it per group](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html), 30d) is required, and the rule abstains if it is absent or zero; CWLogsStoredBytes (AWS/Logs StoredBytes, 30d) is the cross-check for the size gate
