S3 to Lambda Through EventBridge: Cost, Audit, and Routing Trade-offs
Use S3's direct EventBridge integration when you need to filter and route object events to one or more targets. Add CloudTrail data events only when you also need an API-level audit record containing details such as the caller and request operation.
CloudTrail is not required merely to route an S3 object-created event through EventBridge. That distinction removes an unnecessary service from many designs and changes the cost model completely.
Before you start
| Level | Intermediate |
| You should already know | S3 notifications, EventBridge rules, and Lambda invocation basics |
| Reading time | 12 minutes |
| Practice time | 20 minutes |
| Evidence | AWS service behavior and prices are sourced; architecture and CDK are illustrative |
| Pricing checked | 25 July 2026 |
| Technical review | Pending human technical review |
By the end, you will be able to:
- Choose the correct S3-to-EventBridge event source for a stated requirement.
- Calculate CloudTrail data-event charges from request volume.
- Add filtering, retry, and dead-letter handling to an EventBridge target.
- Define the metrics and test events that prove delivery is working.
Why this matters
Two event paths can look similar on an architecture diagram:
S3 service event -> EventBridge -> Lambda
S3 API call -> CloudTrail data event -> EventBridge -> Lambda
They are not interchangeable.
The first path reports that something happened to an S3 object. It is the normal choice for application routing. The second records an API call through CloudTrail and can answer audit questions about the request. It also adds CloudTrail data-event charges and a separate event shape.
If a design adds CloudTrail only because an older example says EventBridge needs it, the workload pays for audit collection without establishing an audit requirement.
Architecture at a glance
Path A: direct S3 service events
S3 bucket
-> default EventBridge bus
-> rule matching bucket, event type, prefix, or suffix
-> Lambda target
-> SQS dead-letter queue for failed target delivery
After EventBridge delivery is enabled on a bucket, S3 sends supported bucket events to the default event bus. EventBridge rules perform the filtering. This is useful for routing one event to multiple consumers or applying richer event-pattern matching than a basic bucket notification.
Path B: CloudTrail data events
S3 API request
-> CloudTrail trail configured for selected S3 data events
-> default EventBridge bus
-> rule matching "AWS API Call via CloudTrail"
-> Lambda target
Use this path when the identity and API-call record are part of the requirement. The trail must be configured to capture the relevant S3 data events. A management-event trail alone does not capture high-volume object operations such as PutObject.
The event schemas differ, so a Lambda handler written for the direct S3 event cannot safely assume that a CloudTrail event has the same fields.
Choose the event source from the question you need to answer
| Requirement | Better default | Reason |
|---|---|---|
| Start processing when an object is created | Direct S3 event to EventBridge | Fewer components and no CloudTrail data-event dependency |
| Route object events to several consumers | Direct S3 event to EventBridge | EventBridge rules provide fan-out and filtering |
Record who called PutObject and from where |
CloudTrail data event | The API audit record is the requirement |
| Investigate denied or unusual S3 API calls | CloudTrail data event | Identity and request metadata matter |
| Buffer a slow, single consumer | S3 to SQS to Lambda | A queue solves backpressure; EventBridge alone does not |
Do not use the CloudTrail path as a substitute for a queue. EventBridge retries target delivery, but it is not a workload backlog that operators can throttle and drain like SQS.
Implement the direct EventBridge path
The following CDK TypeScript is illustrative. It shows the relationship between the bucket, rule, Lambda target, and dead-letter queue; it has not been deployed as part of this lesson.
// Illustrative
const bucket = new s3.Bucket(this, "Uploads", {
eventBridgeEnabled: true,
enforceSSL: true,
});
const failedDeliveries = new sqs.Queue(this, "EventDeliveryDlq", {
encryption: sqs.QueueEncryption.SQS_MANAGED,
retentionPeriod: Duration.days(14),
});
const rule = new events.Rule(this, "UploadedDocuments", {
eventPattern: {
source: ["aws.s3"],
detailType: ["Object Created"],
detail: {
bucket: { name: [bucket.bucketName] },
object: { key: [{ prefix: "incoming/" }] },
},
},
});
rule.addTarget(new targets.LambdaFunction(processor, {
deadLetterQueue: failedDeliveries,
retryAttempts: 8,
}));
The rule filters before invoking Lambda, which avoids paying for and operating invocations that the application will discard. The dead-letter queue shown here captures EventBridge target-delivery failures. It does not capture every application-level failure after Lambda accepts the event; the Lambda function still needs its own error handling and idempotency strategy.
Add CloudTrail only when audit evidence is required
For the CloudTrail path, scope advanced event selectors to the bucket and operations that matter. Capturing every S3 object read and write across every bucket creates cost and noise.
The selection boundary should be written as a reviewable requirement:
Capture write-only S3 data events for the production uploads bucket.
Retain the trail according to the audit policy.
Do not capture read events unless the audit requirement includes object access.
CloudTrail data events reach EventBridge with a CloudTrail-oriented detail type. Match the API event explicitly, and test the real event envelope before writing the production handler.
{
"source": ["aws.s3"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["s3.amazonaws.com"],
"eventName": ["PutObject", "CompleteMultipartUpload"]
}
}
This event pattern is illustrative. Your trail selector, bucket boundary, multipart behavior, and EventBridge event must be tested together.
Cost model
The old version of this article multiplied CloudTrail data-event cost by three in one section and used the correct formula in another. Use one explicit calculation instead.
AWS listed CloudTrail trail data events at $0.10 per 100,000 events delivered when pricing was checked on 25 July 2026. S3 storage, CloudWatch Logs delivery, Lambda, EventBridge, cross-Region transfer, archives, and downstream services are separate.
For ten million captured S3 data events in one month:
10,000,000 events / 100,000 = 100 billing units
100 billing units × $0.10 = $10 CloudTrail data-event delivery
For ten million events per day over a 30-day month:
300,000,000 events / 100,000 = 3,000 billing units
3,000 billing units × $0.10 = $300 CloudTrail data-event delivery
These calculations cover CloudTrail data-event delivery only. They do not include S3 storage for trail files, Lambda requests and duration, log ingestion, EventBridge opt-in data events, archives, replay, or data transfer.
EventBridge pricing distinguishes management events, custom events, partner events, cross-account delivery, and opt-in AWS data events. Use the current EventBridge pricing table for the Region and event class rather than copying a custom-event price onto an S3 service event.
What breaks and how you detect it
| Symptom or signal | Likely cause | What to inspect | Safe response |
|---|---|---|---|
| No Lambda invocation after an upload | EventBridge delivery not enabled, rule does not match, or target permission is missing | Bucket notification configuration, rule matched-events metric, target failed-invocations metric | Send a controlled test object and compare its real event with the rule |
| Direct events work but CloudTrail events do not | Trail is not capturing S3 data events | Trail advanced event selectors and logging status | Add the narrow data-event selector and wait for delivery |
| Duplicate processing | At-least-once delivery or target retry | Object identity and application logs | Make the handler idempotent using bucket, key, and version or sequencer data |
| Dead-letter queue grows | EventBridge cannot deliver to the target | DLQ payload, Lambda resource policy, throttles, target availability | Correct the delivery failure, then replay deliberately |
| Audit cost grows unexpectedly | Read and write events or too many buckets are captured | CloudTrail usage and event selectors | Narrow selectors to the required operations and resources |
Security and cost
Security baseline
- Restrict the Lambda resource policy to the intended EventBridge rule.
- Encrypt sensitive buckets, trail destinations, queues, and logs according to data classification.
- Keep the CloudTrail log bucket private and separate audit-log administration from workload administration.
- Scope trail selectors to named resources and required event categories.
- Treat event payloads as untrusted input; object keys and metadata can contain unexpected values.
- Do not place secrets or personal data in event-detail fields or application logs.
Cost assumptions
Region: Confirm for the workload; example arithmetic uses the public USD trail rate
Currency: USD
Usage assumption: 10 million captured data events in one month
CloudTrail unit price: $0.10 per 100,000 data events delivered
Calculation: 10,000,000 / 100,000 × $0.10
CloudTrail subtotal: $10
Excludes: EventBridge, Lambda, S3 trail storage, CloudWatch, archives, replay and transfer
Sensitivity: Cost scales with captured events and duplicate trail copies
Pricing checked: 25 July 2026
Practice: choose and price the event path
Safety: This exercise creates no AWS resources, needs no credentials, and has no cleanup step.
Goal
Choose an event source and calculate the CloudTrail portion of the cost for one workload.
Steps
- Write the trigger requirement in one sentence: application routing, API audit, or both.
- Estimate monthly object creates, reads, deletes, and multipart completions separately.
- Choose direct S3 events, CloudTrail data events, or both.
- If using CloudTrail, identify the exact operations and buckets its selector will capture.
- Calculate the trail data-event charge using the current official rate.
- Define one test event, one failure destination, and one alarm owner.
Verify the result
The exercise is complete only when another engineer can reproduce the event-count calculation and explain why CloudTrail is present or absent.
Clean up
No resources are created.
Verify cleanup
Confirm that the exercise did not enable EventBridge delivery, create a trail, or deploy a rule in any AWS account.
Check your learning
- Does S3 require CloudTrail to send object-created service events to EventBridge?
- When is the CloudTrail event path justified?
- What is the CloudTrail data-event delivery charge for 50 million captured events at $0.10 per 100,000?
- Why does an EventBridge target DLQ not replace application-level idempotency?
Review the answers
- No. EventBridge delivery can be enabled directly on the S3 bucket.
- When the requirement needs an API audit record or CloudTrail-specific request and identity details.
50,000,000 / 100,000 × $0.10 = $50, excluding all other services.- The DLQ handles failed target delivery; duplicate or repeated accepted events can still reach application code.
Before you ship
- [ ] The design says whether the requirement is routing, audit, buffering, or a combination.
- [ ] Direct S3 and CloudTrail event schemas have separate tested fixtures.
- [ ] EventBridge rules filter by the intended bucket and event type.
- [ ] Lambda processing is idempotent.
- [ ] Target retries and a dead-letter queue are configured and owned.
- [ ] CloudTrail selectors capture only the required resources and operations.
- [ ] Cost calculations include event volume, unit price, date, and exclusions.
- [ ] A controlled upload proves the full delivery path before production traffic is enabled.
Sources and verification
- Using EventBridge with Amazon S3
- Enabling EventBridge for an S3 bucket
- AWS service events delivered through CloudTrail
- Amazon EventBridge pricing
- AWS CloudTrail pricing
- Code status: Illustrative. The CDK and event pattern explain the design and are not claimed as a deployed reference.
- Technical review: Pending human technical review.
Continue learning
- Next lesson: S3 to Lambda: Direct Trigger vs SQS in the Middle
- Related reference: Amazon S3 Event Notifications
Correction history
- 2026-07-25: Replaced the CloudTrail-required routing model with separate direct-event and audit-event paths; corrected CloudTrail cost arithmetic and removed unsupported incident claims.