CloudTrail is partly free. The event history of management events (the last 90 days) is free, and so is the first copy of management events a trail delivers in each Region. The main charges are additional copies of management events ($2.00 per 100,000 events), data events and network activity events ($0.10 per 100,000 events from the first copy), Insights, and CloudTrail Lake. CloudTrail's unit prices in the Price List are the same in Tokyo and N. Virginia (checked with the AWS Price List Bulk API on October 26, 2026).
| Item | Price (USD, excluding tax) |
|---|---|
| Event history (management events, last 90 days) | Free |
| Management events from a trail, first copy (per Region) | Free |
| Management events from a trail, additional copies | $2.00 per 100,000 events |
| Data events (from the first copy) | $0.10 per 100,000 events |
| Network activity events (from the first copy) | $0.10 per 100,000 events |
| Data event aggregation (added to the data event charge) | $0.03 per 100,000 events analyzed |
| Insights (management events / data events) | $0.35 / $0.03 per 100,000 events analyzed |
| Direct delivery to CloudWatch Logs without a trail | $0.25 per GB + CloudWatch Logs ingestion |
| CloudTrail Lake (closed to new customers) | Ingestion $0.75 per GB, among other charges |
| S3 for the log files (billed separately, Tokyo) | S3 Standard $0.025 per GB-month |
Rule of thumb: with one multi-Region trail recording management events only, your CloudTrail bill is $0. What you pay is S3 storage for the logs and similar costs.
How to create a trail and set up encryption and log file integrity validation is covered in the complete AWS CloudTrail guide. This article covers pricing only.
What's free in CloudTrail and what isn't
I checked the unit prices against the CloudTrail price file in the AWS Price List Bulk API (published 2026-09-11, effective 2026-07-01). All 14 usage types have the same unit price in Tokyo (APN1-) and N. Virginia (USE1-), and they match the figures on the pricing page.
Free
- Event history. You can view the last 90 days of management events in the console or with the
lookup-eventsAPI (one account and one Region at a time). - The first copy of management events from a trail. "The first copy of management events within each region is delivered free of charge." On the bill it appears only as an event count under
FreeEventsRecorded($0). - The Insights baseline. The analysis that builds a baseline from the past 28 days is free.
Charged even for the first copy
- Data events and network activity events. "For data events, all deliveries incur CloudTrail costs, including the first." Network activity events are always charged as well.
- Direct delivery to CloudWatch Logs without creating a trail. The $0.25/GB is CloudTrail's delivery charge, and CloudWatch Logs ingestion is added on top. Example 10 on the pricing page (N. Virginia) comes to $256 + $512 = $768 for 1,024 GB. An estimate for Tokyo is $0.25 + $0.76 = $1.01 per GB (the $0.25 comes from the pricing page only; the Price List has no per-Region unit price for it). When a trail sends events to CloudWatch Logs, standard CloudWatch Logs pricing applies.
- Broken trails. If a trail can't reach its S3 bucket, CloudTrail keeps retrying delivery for 30 days, and those attempts are charged. To stop it, delete the trail.
I can take on the implementation from this article as an engagement
Security engineering, from design to implementation and operations
Reading your bill: PaidEventsRecorded and other usage types
On your bill and in Cost Explorer, each CloudTrail line item shows a Region code followed by a usage type.
| Usage type (Tokyo example) | Meaning | Where to look for the cause |
|---|---|---|
APN1-FreeEventsRecorded | First copy of management events ($0) | The count delivered by the first-copy trail. With no exclusions, that Region's monthly management event count |
APN1-PaidEventsRecorded | Additional copies of management events | Two or more trails record the same management events |
APN1-DataEventsRecorded | Data events (always charged) | Which trail records which resources |
APN1-NetworkEventsRecorded | Network activity events (always charged) | Event selection for VPC endpoints |
APN1-EventsAnalyzed-AggregatedEvents | Data event aggregation | Trails with aggregation enabled |
APN1-InsightsEvents / APN1-DataInsightsEvents | Events analyzed by Insights (management / data) | How many Insights types are enabled, and on what |
APN1-Ingestion-Bytes… / APN1-PaidStorage-ByteHrs / APN1-QueryScanned-Bytes | CloudTrail Lake ingestion / extended retention / queries | Event data stores |
If you see PaidEventsRecorded, management events are being delivered more than once in that Region. AWS describes it as "The charge for additional copies of management events delivered to an AWS Region."
Find the usage type in Cost Explorer
In the console, open Cost Explorer, choose Usage type under Group by, and narrow Service to CloudTrail under Filters. For event counts, use UsageQuantity from the Cost Explorer API.
# 1) Look up CloudTrail's service name in the billing data (don't guess the spelling)
aws ce get-dimension-values \
--time-period Start=2026-09-01,End=2026-10-01 \
--dimension SERVICE --search-string CloudTrail \
--query 'DimensionValues[].Value'
# 2) Event count and cost per usage type. Put the name printed by 1) in Values
aws ce get-cost-and-usage \
--time-period Start=2026-09-01,End=2026-10-01 \
--granularity MONTHLY \
--metrics UsageQuantity UnblendedCost \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["<service-name-printed-by-step-1>"]}}'
The End date is exclusive. UsageQuantity is summed across different units, so always group by usage type.
Trail tags can't split the cost. AWS Billing can't use a trail's tags for cost allocation; cost allocation tags work on the S3 bucket and on Lake event data stores (per the user guide).
Find the trail that causes the charge
# Every trail in the account, with its home Region
aws cloudtrail list-trails
# Trails in the current Region plus shadow trails (copies from other Regions, organization trails)
aws cloudtrail describe-trails \
--query 'trailList[].{Name:Name,MultiRegion:IsMultiRegionTrail,Org:IsOrganizationTrail,Home:HomeRegion}'
# The events that trail records (its selectors)
aws cloudtrail get-event-selectors --trail-name <trail-name-or-ARN>
Trail pricing: which setups turn management events into a "second copy"
Rule: in each Region, only the first copy of a management event is free.
| Case | Setup | Management event charge |
|---|---|---|
| A | Two single-Region trails (one in us-east-1, one in us-west-2) | Free (each is the first copy in its Region) |
| B | A multi-Region trail + a single-Region trail | The single-Region trail is charged in its Region |
| C | Two multi-Region trails | One of them is charged as a second copy in every Region |
| D | An organization trail + a member account trail that collects the same management events | The member account's trail is charged |
Case B can also come from a difference in defaults. In Terraform's aws_cloudtrail, is_multi_region_trail defaults to false (the console defaults to multi-Region). Leave it unset and you get a single-Region trail, charged as a second copy in that Region.
Case D also happens with Control Tower. Control Tower creates an organization trail when it sets up the landing zone, and AWS warns that unless you delete an account's existing trail before enrolling it, you may see duplicate charges. Cleaning up organization trails is covered in building a company-wide CloudTrail audit platform with AWS Organizations.
How to estimate your own monthly bill
Monthly cost = monthly event count ÷ 100,000 × the unit price per 100,000 events. Take the counts from your own billing data or logs.
- Management events. If the first-copy trail records both read and write events with no exclusions, the
FreeEventsRecordedcount on your bill is that Region's monthly management event count. Check for exclusions withget-event-selectors. If you create a second trail that records all of the same management events, its second-copy count will be the same number. - Data events. AWS publishes no formula for estimating them in advance. Enable them on a narrow scope (one bucket, writes only, for example) for a short period, read the daily
DataEventsRecordedcount with--granularity DAILY, and multiply by 30. - Count from the logs in S3. Create the official partition projection table in Athena (one table per Region) and you can count events by event source.
-- Example that assumes cloudtrail_logs_pp, the AWS official partition projection table
SELECT eventsource, eventcategory, count(*) AS events
FROM cloudtrail_logs_pp
WHERE "timestamp" BETWEEN '2026/09/01' AND '2026/09/30' -- narrow the period to limit the data scanned
GROUP BY eventsource, eventcategory
ORDER BY events DESC
LIMIT 20;
Worked examples (all counts are hypothetical)
| Case | Input (hypothetical counts) | Calculation | Monthly |
|---|---|---|---|
| 1. One multi-Region trail, management events only | 2,000,000 first-copy events in Tokyo | 2,000,000 × $0 | $0.00 |
| 2. Case 1 plus a single-Region trail in Tokyo that records the same management events | 2,000,000 second-copy events | 2,000,000 ÷ 100,000 × $2.00 | $40.00 |
| 3. S3 data events, one bucket, writes only | 500,000 a day × 30 days = 15,000,000 | 15,000,000 ÷ 100,000 × $0.10 | $15.00 |
| 4. Case 3 plus reads | 5,000,000 reads a day × 30 days = 150,000,000 | $15.00 + 150,000,000 ÷ 100,000 × $0.10 | $165.00 |
| 5. Case 3 plus aggregation | 15,000,000 | $15.00 + 15,000,000 ÷ 100,000 × $0.03 | $19.50 |
| 6. Insights, two types (management events) | 300,000 writes and 2,700,000 reads → analyzed 300,000 × 2 + 2,700,000 = 3,300,000 | 3,300,000 ÷ 100,000 × $0.35 | $11.55 |
| 7. Data events for every bucket, unfiltered | 100,000,000 a day × 30 days = 3,000,000,000 | 3,000,000,000 ÷ 100,000 × $0.10 | $3,000.00 |
Pricing for data events, Insights, network activity events, and aggregation
Data events
Data events record operations inside a resource, such as S3 object GetObject, PutObject, and DeleteObject, or Lambda Invoke. They tend to be high-volume and are not logged by default.
- Every copy is charged. If two trails record the same data event, you pay twice. When an operation comes from another account and both accounts' trails record it, the caller and the owner each pay.
- Watch for recursive logging. If you log S3 data events on the log bucket itself, CloudTrail's own log delivery (
PutObject) gets recorded, and that record is delivered again. SettingRecursiveLoggingto false stops it (the default is true).
# Run in the trail's home Region
aws cloudtrail update-trail --name <trail-name> --no-recursive-logging
The Terraform aws_cloudtrail documentation has no argument for this (as of October 26, 2026), so another option is to exclude the log bucket with not_starts_with on resources.ARN.
Narrow data events to the target buckets with advanced event selectors, and keep management events with no exclusions. The example below records writes on the target bucket only. Without reads, there is no record of who read an object. For a bucket with sensitive data, remove the readOnly condition.
resource "aws_cloudtrail" "audit" {
# Creation fails without the bucket policy (InsufficientS3BucketPolicyException)
depends_on = [aws_s3_bucket_policy.cloudtrail]
# Definitions of the KMS key, log group, IAM role and bucket policy are omitted
name = "audit-trail"
s3_bucket_name = aws_s3_bucket.cloudtrail.id
is_multi_region_trail = true # defaults to false
include_global_service_events = true
enable_log_file_validation = true # defaults to false (CloudTrail.4)
kms_key_id = aws_kms_key.cloudtrail.arn # CloudTrail.2
cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.cloudtrail.arn}:*" # CloudTrail.5. The trailing :* is required
cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_to_logs.arn
# Management events: record reads and writes, with no exclusions
advanced_event_selector {
name = "All management events"
field_selector {
field = "eventCategory"
equals = ["Management"]
}
}
# Data events: record writes on the target bucket only (reads are not recorded)
advanced_event_selector {
name = "S3 write data events on the target bucket"
field_selector {
field = "eventCategory"
equals = ["Data"]
}
field_selector {
field = "resources.type"
equals = ["AWS::S3::Object"]
}
field_selector {
field = "readOnly"
equals = ["false"]
}
field_selector {
field = "resources.ARN"
starts_with = ["${aws_s3_bucket.audited.arn}/"] # the trailing / is required
}
}
}
Once you apply advanced selectors, they overwrite that trail's basic selectors.
Insights
Insights emits an event when the API call rate or the error rate moves away from a baseline built from the past 28 days. The charge is the total number of events analyzed across Insights types × $0.35 (management events) or $0.03 (data events) per 100,000.
- With both types enabled on management events, write events are analyzed twice and read events once (API call rate looks at write events only). In the user guide's example, 270,000 reads and 30,000 writes come to 330,000 events analyzed.
- With both types enabled on data events, every event is analyzed twice. Insights for data events is available on trails only.
- Insights analyzes the events the trail recorded, so excluding events on the trail also lowers the number analyzed.
Network activity events and aggregation
Network activity events let a VPC endpoint owner record the AWS API calls made through the endpoint; they are not logged by default. Data event aggregation produces five-minute summaries and adds $0.03 per 100,000 events on top of the data event charge (the original charge does not go down).
Costs CloudTrail doesn't charge for (but still show up on your bill)
Some of the surrounding services cost more in Tokyo (for example, CloudWatch Logs ingestion is $0.76/GB in Tokyo and $0.50/GB in N. Virginia). The table lists Tokyo unit prices (checked against each service's Price List on October 26, 2026).
| Service / item | Tokyo unit price |
|---|---|
| S3 Standard storage (first 50 TB) | $0.025 per GB-month |
| S3 PUT, COPY, POST, LIST | $0.0047 per 1,000 requests |
| S3 Glacier Instant Retrieval storage | $0.005 per GB-month |
| S3 Lifecycle transitions (to Glacier Instant Retrieval) | $0.02 per 1,000 requests |
| KMS requests | $0.03 per 10,000 requests |
| KMS customer managed key | $1 per key version per month |
| CloudWatch Logs ingestion (Standard log class) | $0.76 per GB |
| CloudWatch Logs storage | $0.033 per GB-month |
| SNS API requests (first 1 million each month are free) | $0.50 per 1 million |
| Athena data scanned (10 MB minimum per query) | $5.00 per TB |
- S3. CloudTrail delivers log files (gzip) with
PutObjectabout every 5 minutes and keeps them indefinitely by default. Until you add an expiration rule, storage keeps piling up. - CloudWatch Logs. Sending a trail to CloudWatch Logs incurs ingestion and storage charges. As an estimate, ingesting 10 GB a month at the Standard rate costs 10 × $0.76 = $7.60. If you still have free tier left, the Price List shows the first 5 GB of ingestion at $0, so it would be (10 − 5) × $0.76 = $3.80 (check the actual usage types on your own bill). How the services' roles differ is covered in CloudTrail vs CloudWatch vs AWS Config.
- GuardDuty. The charge for analyzing CloudTrail management events appears on the GuardDuty bill. The breakdown is in Amazon GuardDuty pricing and cost optimization.
CloudTrail Lake: ingestion and query pricing, retention options, and the end of new sign-ups
CloudTrail Lake stopped accepting new customers on May 31, 2026. AWS announced the change in the user guide's document history, in an entry dated March 31, 2026.
- Existing customers can keep using it, but from here on it gets only critical bug fixes and security updates.
- Trails, Insights, and aggregated events are not affected.
- AWS recommends CloudWatch as the migration target. Data from before 2023 is not migrated. Sending events to CloudWatch Logs without a trail incurs both the delivery charge and the ingestion charge (see above).
- The pricing page still mentions a 30-day free trial, but new customers can't use it.
Pricing for existing customers (the same in Tokyo and N. Virginia):
| Pricing option | Ingestion | Retention | Queries |
|---|---|---|---|
| One-year extendable retention (default) | CloudTrail events $0.75/GB, other sources $0.50/GB | 366 days by default, up to 3,653 days. $0.023/GB-month beyond one year | $0.005/GB scanned |
| Seven-year retention | $2.5/GB for the first 5 TB a month, $1/GB for the next 20 TB, $0.50/GB above 25 TB | 2,557 days | $0.005/GB scanned |
Ingestion is billed on uncompressed data; retention and queries are billed on optimized, compressed data. GB is binary (1 TB = 1,024 GB). As an estimate, ingesting 1,024 GB costs 1,024 × $0.75 = $768.00. The migration steps and how to choose between Lake and Athena are in the CloudTrail Lake practical guide.
How to lower the bill without breaking audit requirements
- Delete duplicate trails. Once the duplicates are gone,
PaidEventsRecordedstops. If you have an organization trail (including one Control Tower created), clean up the duplicates on the member side too. - Narrow data events. Narrow the target buckets first. Dropping reads cuts more, but then there is no record of who read an object. Keep reads for buckets with sensitive data.
- Stop recursive logging. Use
--no-recursive-logging, or exclude the log bucket from the scope. - Delete broken trails. The 30 days of redelivery attempts are charged too.
- Apply KMS and RDS Data API exclusions to additional trails only. The main trail carries the first copy, so excluding them there does not lower CloudTrail's delivery charge (it only reduces what flows to S3 and CloudWatch Logs and, if Insights is enabled, the number of events analyzed). The way to reduce KMS events at the source is S3 Bucket Keys (according to AWS, they cut KMS request costs by up to 99% and also reduce the KMS events in CloudTrail).
- Set retention with S3 Lifecycle. Start with an
expirationrule that matches your audit requirements. - Narrow Athena queries to partitions by period. Without a condition, Athena scans every file.
- Set a budget alert. The user guide names creating a CloudTrail budget in AWS Budgets as a best practice. In Terraform's
aws_budgets_budget, usefilter_expressionrather thancost_filter, which maps to the deprecatedCostFiltersAPI, and use the result ofget-dimension-valuesabove as the Service value. FinOps across the whole account is covered in the Terraform × FinOps guide to cutting a startup's AWS bill.
A note on step 5: KMS Encrypt, Decrypt, and GenerateDataKey usually make up more than 99% of KMS events, and they are recorded as read events.
# Run in the trail's home Region.
# Use only on an additional (paid) trail; never apply it to the main multi-Region trail
aws cloudtrail put-event-selectors \
--trail-name <additional-trail-name> \
--event-selectors '[{"ReadWriteType": "All","IncludeManagementEvents": true,"ExcludeManagementEventSources": ["kms.amazonaws.com","rdsdata.amazonaws.com"]}]'
For a trail managed in Terraform, set exclude_management_event_sources = ["kms.amazonaws.com", "rdsdata.amazonaws.com"] in the event_selector block (it can't be combined with advanced_event_selector). A change made with the CLI shows up as a Terraform diff, and the next apply may revert it.
If step 6 also adds storage class transitions, keep these points in mind:
- Objects smaller than 128 KB don't transition by default (for lifecycle configurations created or modified since September 2024). Transition request charges can outweigh the savings, so AWS doesn't recommend transitioning small objects. AWS publishes only the maximum size of a CloudTrail log file (50 MB uncompressed), not a typical size, so check your own bucket before you decide.
- The minimum storage durations are 30 days for Standard-IA, 90 days for Glacier Instant Retrieval, and 180 days for Deep Archive. Standard-IA and Glacier Instant Retrieval bill objects smaller than 128 KB as 128 KB.
- You can't use a lifecycle configuration on a bucket with MFA Delete enabled. Versions locked by Object Lock are not deleted, even by an expiration rule.
What not to cut
In an account evaluated by Security Hub or the CIS Benchmark, removing any of the following four to save money fails the check.
| Security Hub control | CIS v5.0.0 | If you remove it to save money |
|---|---|---|
| CloudTrail.1: at least one multi-Region trail that includes read and write management events (severity High) | 3.1 | Exclusions or dropping reads fail it |
| CloudTrail.4: log file integrity validation is enabled | 3.2 | Fails. The Price List has no charge item for it; the only cost is S3 charges for the hourly digest files |
| CloudTrail.2: encryption at rest is enabled | 3.5 | Fails. Keep KMS charges down with S3 Bucket Keys |
| CloudTrail.5: the trail is integrated with CloudWatch Logs | 3.4 | Fails. The cost is CloudWatch Logs pricing (in Tokyo, $0.76/GB ingestion and $0.033/GB-month storage) |
The two controls that bring separate KMS or CloudWatch Logs charges are CloudTrail.2 and CloudTrail.5. AWS names CloudWatch Logs integration as a way to analyze events in real time. For an account that is not evaluated, weigh the need for real-time alerts against the ingestion charge.
The AWS Config rule multi-region-cloudtrail-enabled, which evaluates CloudTrail.1, describes it as follows:
The rule is NON_COMPLIANT if the ExcludeManagementEventSources field is not empty or if AWS CloudTrail is configured to exclude management events such as AWS KMS events or Amazon RDS Data API events.
Excluding KMS or RDS Data API events on your main multi-Region trail fails CloudTrail.1. Framework-specific requirements, such as PCI DSS Requirement 10, are explained in preparing for compliance audits with AWS CloudTrail.
If you want your AWS configuration checked as a whole, including duplicate trails, data event scope, and log protection, see the security audit.