AWS Builder Center: Learn, Build and Connect with builders in the AWS community
AWS Builder Center is the official home for builders on AWS. Share and read what others are working on, follow people who inspire you, explore training and workshops, and find tools to support what you're building.
Comparing Amazon S3 server access log delivery and query costs
S3 server access logs can now be delivered to Amazon CloudWatch Logs as well as to an S3 general purpose bucket, with two log classes, an optional S3 Tables integration for SQL analytics, and Intelligent Tiering storage. The billing dimensions differ, so a like-for-like comparison is not obvious. This post prices every option against the same traffic, retention, and query scenarios, at 1,000 and 1,000,000 requests per minute.
Amazon S3 server access logging (SAL) can deliver to an S3 general purpose bucket, and now to Amazon CloudWatch Logs. CloudWatch delivery supports two log classes, an optional S3 Tables integration for SQL analytics, and Intelligent Tiering storage that lowers storage cost as data ages. This post compares their costs using the same traffic, retention, and query scenarios.
Summary
- CloudWatch delivery is worth the ingestion charge if you actually query your logs. Structured queries within seconds, and a one-day aggregation at 1,000,000 req/min costs $0.40 on S3 Tables against $589 on unpartitioned SAL, or $6.55 once you build and maintain the partitioned Athena table yourself.
- S3 Tables adds $0, and CloudWatch delivery is the only path to it. No custom ETL, no table maintenance, just Athena at $5/TB scanned.
- Its cost premium shrinks the more logs you send. Ingestion tiers are cumulative per account and Region, and Intelligent Tiering drops storage as data ages. Past 50 TB/month of vended logs, CloudWatch with 90-day retention comes in slightly under SAL on total cost.
- SAL to S3 still wins on pure collection cost, since delivery is free. That is the right choice only if the logs sit unread.
Delivery options
- Original SAL to S3. Delivery is free. Space-delimited text objects incur S3 storage and query charges.
- CloudWatch Logs Standard log class. Structured fields are queryable within seconds. Standard supports metric filters and alarms, Live Tail, subscription filters, and the
GetLogEventsandFilterLogEventsAPIs. - CloudWatch Logs Infrequent Access log class. Structured Logs Insights queries and S3 Tables integration at lower ingestion rates, but without those Standard-only features.
- S3 Tables integration. Either log class can mirror logs into managed Apache Iceberg tables for Athena and other SQL engines. AWS charges no incremental storage or table-maintenance fee.
The Standard and Infrequent Access log classes have the same storage and Logs Insights query prices. Only ingestion pricing differs between them. Separately, Intelligent Tiering storage can lower the storage price for either class.
Assumptions
The comparison uses sustained rates of 1,000 and 1,000,000 requests per minute, equivalent to 43.2 million and 43.2 billion requests in a 30-day month. It assumes:
- 90-day retention at steady state (enforced by S3 Lifecycle for logs delivered to S3 general purpose buckets).
- An average SAL record is 1,000 bytes, driven mainly by key name and user-agent string length. Measure your logs for a precise estimate.
- CloudWatch compresses logs to approximately 15% of ingested size for storage billing.
- In these calculations, 1 GB means 1 GiB (2³⁰ bytes) and 1 TB means 1 TiB (2⁴⁰ bytes), consistent with AWS pricing.
- Original SAL storage is modelled on the Standard storage class. By default, S3 Lifecycle does not transition objects smaller than 128 KB to any storage class. Whether a transition would reduce cost depends on retention, and the size of the objects SAL delivers, which this post does not measure.
- S3 Standard is priced at $0.023/GB for the 1,000 req/min example and $0.021/GB (top volume tier) for the 1,000,000 req/min examples.
- CloudWatch storage figures assume Intelligent Tiering storage is enabled and historical analysis runs in S3 Tables, so retained data is not read in CloudWatch and tiers down without promotion, with log volume spread evenly across each day of the retention window. Without Intelligent Tiering enabled, or where old data is queried in CloudWatch, storage bills at up to the flat Standard rate of $0.03/GB.
- US East (N. Virginia) prices, verified 2026-07-16.
- Calculated costs and capacities are rounded to three significant figures for easier reading.
Monthly cost
Monthly ingestion cost is based on the volume delivered that month and is unaffected by retention. With 90-day retention, steady-state storage contains approximately three months of logs.
S3 Tables adds $0 to each total.
1,000 req/min
This generates approximately 40.2 GB/month and retains approximately 121 GB.
| Original SAL | CloudWatch Standard | CloudWatch IA | |
|---|---|---|---|
| Ingestion | $0 | $20.10 | $10.10 |
| Storage | $2.78 | $0.40 | $0.40 |
| Total | $2.78 | $20.50 | $10.50 |
1,000,000 req/min, starting from zero vended-log usage
This generates approximately 39.3 TB/month and retains approximately 118 TB.
| Original SAL | CloudWatch Standard | CloudWatch IA | |
|---|---|---|---|
| Ingestion | $0 | $11,200 | $6,350 |
| Storage | $2,530 | $398 | $398 |
| Total | $2,530 | $11,600 | $6,750 |
The high-volume calculations for CloudWatch, accounting for vended-log volume tiering, are:
- Standard ingestion: 10,240 GiB × $0.50 + 20,480 GiB × $0.25 + 9,513.1 GiB × $0.10 = $11,200.
- IA ingestion: 10,240 GiB × $0.25 + 20,480 GiB × $0.15 + 9,513.1 GiB × $0.075 = $6,350.
- CloudWatch storage: 6,035.0 GiB × $0.03 + 12,069.9 GiB × $0.018 = $398 (Intelligent Tiering, 90-day, analysis in S3 Tables; the compressed corpus is 18,104.9 GiB, one-third in the Standard tier and two-thirds in Infrequent Access).
How cumulative ingestion volume tiers affect the class discount
| Monthly vended-log volume tier | Standard | IA | IA discount |
|---|---|---|---|
| First 10 TB | $0.50/GB | $0.25/GB | 50% |
| Next 20 TB | $0.25/GB | $0.15/GB | 40% |
| Next 20 TB | $0.10/GB | $0.075/GB | 25% |
| Over 50 TB | $0.05/GB | $0.05/GB | 0% |
At 1,000 req/min, IA ingestion costs half of Standard. At 1,000,000 req/min from zero, traffic reaches the third tier and IA's blended discount narrows to approximately 43%.
1,000,000 req/min, when the account already exceeds 50 TB/month
CloudWatch applies vended-log volume tiers cumulatively across sources in an account and Region. If other vended logs already exceed 50 TB/month, every additional GB enters the $0.05/GB top tier for both classes.
| Original SAL | CloudWatch Standard | CloudWatch IA | |
|---|---|---|---|
| Ingestion | $0 | $2,010 | $2,010 |
| Storage | $2,530 | $398 | $398 |
| Total | $2,530 | $2,410 | $2,410 |
Standard and IA cost the same because Standard is discounted to the same price in the top tier. CloudWatch is marginally cheaper than original SAL due to this tiered discount, and by using Intelligent Tiering storage with analysis in S3 Tables.
Reducing CloudWatch storage costs with Intelligent Tiering
CloudWatch Logs Intelligent Tiering is a storage-cost feature, independent of the log class. It is off by default; enable it once per account and Region with PutStorageTierPolicy, and it applies to every log group there, including existing ones. Enabling it and moving data between tiers carry no charge; you pay only for the storage each tier holds.
It classifies stored data into three storage tiers by access recency, at the same query latency:
| Intelligent Tiering storage tier | Moves here after | Storage price |
|---|---|---|
| Standard | default for newly ingested data | $0.03/GB |
| Infrequent Access | 30 days without access | $0.018/GB |
| Archive Instant Access | 90 days without access | $0.006/GB |
A read in CloudWatch — a Logs Insights StartQuery, a FilterLogEvents or GetLogEvents call, or a CreateExportTask export — promotes the data it touches back to the Standard tier for 30 days, resetting the timer. So the storage price follows your access pattern. Interactive investigation in Logs Insights works on recent data, which sits in the Standard tier anyway, so tiering changes neither its cost nor its strengths (results within seconds, time-scoped scans). Historical analysis run in S3 Tables reads the Iceberg mirror in Athena, not the CloudWatch log events, so the CloudWatch copy stays cold and tiers down; the continuous mirror runs at ingestion time and does not count as access. Query recent data live in CloudWatch, analyse the long tail in S3 Tables, and the storage bill for that long tail falls automatically — the case the storage figures in this post model. Regularly querying old data in CloudWatch keeps it in the Standard tier at $0.03/GB, as expected when the data is in active use. A per-tier StoredBytes metric (dimension StorageType) reports how much data sits in each tier, published once per day.
Note the name overlap: "Infrequent Access" is both an ingestion log class and an Intelligent Tiering storage tier — independent axes. The log class is fixed at creation and sets the ingestion price; the storage tier changes automatically with access and sets the storage price. A single log group has both.
What retention changes
Retention changes storage linearly but does not affect ingestion. Intelligent Tiering interacts with retention: the longer data is retained without being read in CloudWatch, the more of it reaches the lower storage tiers. At 30-day retention, data expires before it can leave the Standard tier, so Intelligent Tiering makes no difference; at 90 days about two-thirds of the corpus reaches Infrequent Access; at 180 days about half reaches Archive Instant Access.
At 1,000,000 req/min:
| Retention | Retained volume | CloudWatch storage | Original SAL storage |
|---|---|---|---|
| 30 days | ~39.3 TB | $181 | $845 |
| 90 days | ~118 TB | $398 | $2,530 |
| 180 days | ~236 TB | $507 | $5,070 |
These CloudWatch figures assume Intelligent Tiering is enabled and historical analysis runs in S3 Tables; without either, storage bills at up to the flat Standard rate of $0.03/GB (see Reducing CloudWatch storage with Intelligent Tiering). CloudWatch storage is lower than original SAL because compression reduces billable volume to approximately 15% of raw ingest; Intelligent Tiering widens that gap as retention grows — from approximately 4.7x cheaper than SAL storage at 30 days (compression alone) to approximately 6.4x at 90 days and roughly 10x at 180 days.
What CloudWatch delivery adds
Original SAL delivered to an S3 general purpose bucket has no native path to S3 Tables, requiring custom ETL. The Iceberg mirror is a CloudWatch Logs log group feature, so CloudWatch delivery is a prerequisite for it, not an independent option alongside it.
Both log classes also provide:
- Structured queries with Log Analytics, saved and parameterized queries, facets, natural-language query generation, and visualizations within seconds of delivery. It also brings Live Tail and Contributor Insights into the same console experience where supported.
- Cross-account and cross-Region aggregation through CloudWatch cross-account observability.
Choose the Standard log class when you need metric filters and alarms, Live Tail, subscription filters, or the log-event APIs. Choose the Infrequent Access log class when Logs Insights and Athena provide the required access. A log group's class is fixed when created and cannot later be changed.
What 'no additional cost' for S3 Tables means
You pay for CloudWatch ingestion and storage, plus Athena queries at $5/TB scanned. You do not pay separately for the copy to Iceberg format, S3 Tables storage, or maintenance. Retention follows the CloudWatch log group.
For a KMS-encrypted log group, grant the required access to systemtables.cloudwatch.amazonaws.com and maintenance.s3tables.amazonaws.com. Without those grants, table delivery can stop.
Query cost: partitioning and column pruning
Original SAL does not create an Athena table. By default, its flat prefix gives Athena no date partition to prune, so every query scans the retained corpus. S3 can instead deliver SAL using a date-based key format ([SourceAccountId]/[SourceRegion]/[SourceBucket]/[YYYY]/[MM]/[DD]/...), but you must opt in and build the partitioned Athena table yourself. See Partition your data for Athena setup and partition management.
Partitioning limits the files scanned. It does not enable column pruning because SAL objects remain plain text: Athena reads each selected file in full. S3 Tables stores the data in a columnar Iceberg table, enabling both partition and column pruning.
The same query across all three paths
The original SAL query below uses a date-partitioned table, with schema field mapping tested against a real partitioned SAL object.
SELECT requester, operation, COUNT(*) as request_count FROM s3_access_logs_db.s3_access_logs_partitioned WHERE account_id = '123456789012' AND region = 'us-east-1' AND source_bucket = 'my-source-bucket' AND year = date_format(current_date - interval '1' day, '%Y') AND month = date_format(current_date - interval '1' day, '%m') AND day = date_format(current_date - interval '1' day, '%d') GROUP BY requester, operation ORDER BY request_count DESC LIMIT 20;
CloudWatch Logs Insights uses the time range selected for the query:
stats count(*) as requests by requester, operation
| sort requests desc
Athena on S3 Tables uses cwl__timestamp for partition pruning:
SELECT requester, operation, COUNT(*) as request_count FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access" WHERE cwl__timestamp >= current_date - interval '1' day AND request_time >= current_date - interval '1' day GROUP BY requester, operation ORDER BY request_count DESC LIMIT 20;
Keep the cwl__timestamp predicate. Filtering only on request_time does not prune the managed date partition.
Query costs at 1,000,000 req/min
At approximately 1.3 TB/day and 90-day retention, each row shows the cost to run that query on each path:
| Query | Unpartitioned SAL | Daily-partitioned SAL | Logs Insights | S3 Tables |
|---|---|---|---|---|
| One hour, requester and operation | $589 | $6.55 | $0.28 | $0.40 |
| One day, requester and operation | $589 | $6.55 | $6.71 | $0.40 |
| Seven days, requester and operation | $589 | $45.80 | $46.90 | $2.79 |
| Full 90 days, full record | $589 | $589 | $604 | $589 |
The paths differ in what they can prune. Unpartitioned SAL scans the full 90-day corpus for every query. Daily-partitioned SAL and S3 Tables can filter to an hour, but both still scan the relevant day; their hourly cost therefore matches a one-day query. For this aggregation, Logs Insights is the only path here that reduces the scan to the requested hour. Selecting requester and operation does not reduce its scan volume. In the Standard log class, field indexes can reduce scans for equality filters on indexed values, but they do not apply to this aggregation and are unavailable in the Infrequent Access log class. S3 Tables combines daily partition pruning with column pruning, which reduces its two-field scans below either Athena-over-text or Logs Insights.
S3 Tables column-pruning estimates are approximate and based on measurements of real S3 access-log data. They vary with selected fields, column widths, and query predicates.
Choosing a path
- Choose original SAL for free delivery and infrequent review, ensuring date-based partitioning is enabled for Athena analysis. Lifecycle expiration is essential to manage storage costs.
- Choose the Infrequent Access log class with S3 Tables for immediate structured queries and managed SQL when you do not need Standard-only monitoring features.
- Choose the Standard log class with S3 Tables when you also need alarms, Live Tail, subscription filters, or log-event APIs.
- Enable Intelligent Tiering storage to lower CloudWatch storage cost as data ages, and run historical analysis in S3 Tables to keep that older data in the lower tiers. The saving grows with retention: it does nothing at 30 days, but roughly halves CloudWatch storage at 180 days. Because Intelligent Tiering is set per account and Region, it affects every log group there, not only SAL.
- For any path, set retention explicitly, and constrain queries by time. For Athena, partition and column pruning are the largest query-cost levers.
- Check SAL retention and account-wide CloudWatch vended-log usage. Depending on your usage, retention, and queries it might even be cheaper to switch to CloudWatch and S3 Tables!
- Language
- English
Relevant content
- Accepted Answer
asked 4 years ago
AWS OFFICIALUpdated 5 months ago