Skip to main content

WAF: Change WAF ACL Logging Destination to S3

Difficulty: Easy

Description

We detected WAF Web ACLs in your account that send logs to CloudWatch Logs instead of S3. Vended logs delivery to S3 is approximately 50% cheaper than CloudWatch Logs, and S3 storage costs are also significantly lower. Switching the log destination to S3 can reduce both delivery and storage costs.


Selection Criteria

  • The WAF Web ACL has logging enabled

  • The log destination is CloudWatch Logs


Expected Savings

Around 50% on ingestion plus ~23% on storage, with much deeper savings if S3 lifecycle policies transition older logs to Glacier tiers.

Cost components affected:

Component

CloudWatch Logs

S3

Vended logs delivery (first 10 TB)

$0.50 / GB

~$0.25 / GB

Storage

$0.03 / GB-month

$0.023 / GB-month (Standard)

Long-term retention

$0.03 / GB-month (flat)

Down to $0.004/GB (Glacier Deep Archive)

Example — a WAF Web ACL generating 200 GB/month of vended logs:

  • Before: 200 GB × $0.50 + 200 GB × $0.03 = $106/month

  • After: 200 GB × $0.25 + 200 GB × $0.023 = $54.60/month

  • Savings: ~$51.40/month (~49%) per Web ACL, before any additional S3 lifecycle optimization

Operational Impact

  • Downtime: None — but note that a WAF Web ACL accepts only one logging destination at a time, so the destination must be switched in place via wafv2:PutLoggingConfiguration. The switch is near-instant; a brief gap of a few seconds is possible during the update.

  • Breaking changes: Any downstream consumer reading from the CloudWatch log group (subscription filters, metric filters, Logs Insights saved queries, third-party SIEMs) must be migrated to read from S3 (Athena, S3 Select, or a Lambda processor), or routed through Kinesis Firehose if near-real-time delivery is required.

  • Recovery: Re-pointing the destination back to the CloudWatch log group via wafv2:PutLoggingConfiguration restores the previous behavior. Existing CloudWatch logs are not deleted by the change.

  • ⚠️ Warning — Bucket naming: WAF requires the destination S3 bucket name to start with aws-waf-logs-. Existing buckets that don't follow this convention cannot be used.

  • ⚠️ Warning — Real-time use cases: CloudWatch Logs offers near-real-time ingestion. If alerts depend on this latency, either accept S3 latency or use Kinesis Firehose with S3 as the destination.

  • ⚠️ Warning — Retention & compliance: Configure S3 bucket policy, encryption (SSE-S3 or SSE-KMS), lifecycle, and Object Lock as needed to meet the same governance previously provided by the CloudWatch log group retention policy.

References:

Did this answer your question?