The problem
Event-driven architectures are easy to wire quickly and hard to reason about later. One of the riskiest mistakes is letting an S3 object-created notification trigger a Lambda that writes back into the same bucket. That can create repeated invocations, repeated object creation, and downstream logging cost that grows much faster than expected.
Why it happens
- Teams prototype an S3 processing flow with one bucket and never separate input from output later.
- Event filters are added partially, but not in a way that guarantees the output path is excluded.
- Bucket names live in environment variables, which makes same-bucket reuse easy to miss in reviews.
What this means for cost
The exact impact depends on resource size, retention age, and region, but this pattern is usually worth reviewing because it compounds quietly over time.
How to detect Lambda S3 recursion risk
The highest-signal pattern is an S3 bucket that sends object-created notifications to a Lambda function while that same function configuration still points back to the bucket for outputs or follow-on writes.
Cloud Waste Hunter looks for a specific configuration pattern:
- an S3 bucket sends a Lambda notification
- the notification includes S3 object-created events
- the Lambda function configuration contains an environment-variable value equal to that same bucket name
That is enough to justify review because same-bucket designs are one of the most common ways accidental recursion enters S3-driven Lambda pipelines.
Inspect the bucket notification configuration:
aws s3api get-bucket-notification-configuration --bucket demo-bucket
Then inspect the Lambda configuration:
aws lambda get-function-configuration \
--function-name arn:aws:lambda:us-east-1:123456789012:function:demo
If the bucket sends object-created events to the function and the same bucket name appears in environment variables such as TARGET_BUCKET or OUTPUT_BUCKET, review the write path carefully.
Important caveats
This detector does not read the Lambda code. It cannot prove whether the function writes to the same key space, writes only to a safe prefix, or only reads from the bucket.
That is why the wording here is deliberately “potential recursion risk.” The signal is still valuable because it finds exactly the sort of configuration that deserves human review before request and invocation cost start amplifying.
How to fix Lambda S3 recursion risk
The safest remediation order is:
- move outputs to a different bucket if you can
- if not, isolate outputs to a prefix that is excluded from the event trigger
- verify retries, dead-letter handling, and observability before re-enabling the flow
aws s3api put-bucket-notification-configuration \
--bucket my-source-bucket \
--notification-configuration '{"LambdaFunctionConfigurations":[{"LambdaFunctionArn":"arn:aws:lambda:region:account:function:object-processor","Events":["s3:ObjectCreated:*"],"Filter":{"Key":{"FilterRules":[{"Name":"prefix","Value":"incoming/"}]}}}]}'
How this differs from S3 access logging loop
S3 access logging loop is a direct bucket-logging configuration issue. This detector is different: it looks for event-driven recursion risk between S3 notifications and Lambda configuration.
How Cloud Waste Hunter helps
Cloud Waste Hunter can connect the triggering bucket and the Lambda function in one finding so teams can spot risky same-bucket event flows before they turn into runaway serverless noise and cost. For the broader event-driven review, start from the AWS Serverless Cost Risks guide.
FAQ
Does this detector prove the Lambda writes back to the same bucket?
No. It surfaces a strong heuristic: the function is triggered by S3 object-created events and appears to reference that same bucket in environment variables. Source-code review is still required.
What is the safest fix?
Use separate buckets for input and output whenever possible. If that is not practical, strict prefix isolation and event-filtering are the next safest controls.
Why is the confidence lower than some other configuration detectors?
Because the detector uses configuration evidence rather than direct code inspection. It is designed to catch likely recursion risk, not to prove recursion conclusively.