Lambda Triggers
Lambda is a serverless computing service that runs in an event-driven manner. It integrates with a wide variety of triggers such as object uploads to S3, HTTP requests from API Gateway, and scheduled executions via EventBridge. To configure triggers, you use commands such as aws s3api put-bucket-notification-configuration (for S3), aws lambda add-permission (for resource-based policies), and aws events put-rule combined with aws events put-targets (for EventBridge).
Syntax
# -----------------------------------------------
# Configure an S3 trigger
# -----------------------------------------------
# aws s3api put-bucket-notification-configuration \
# --bucket {bucket-name} \
# --notification-configuration file://{config-JSON-file}
# → Configures S3 bucket object operations (Put, Delete, etc.) as a Lambda trigger
# Example: aws s3api put-bucket-notification-configuration \
# --bucket akane-evidence-bucket \
# --notification-configuration file://s3-notification.json
# -----------------------------------------------
# Grant a resource-based policy (aws lambda add-permission)
# -----------------------------------------------
# aws lambda add-permission \
# --function-name {function-name} \
# --statement-id {statement-ID} \
# --action lambda:InvokeFunction \
# --principal {service-principal} \
# --source-arn {trigger-resource-ARN}
# → Grants the trigger source service permission to invoke the Lambda function
# Example: aws lambda add-permission \
# --function-name akane-inspect-handler \
# --statement-id s3-invoke-permission \
# --action lambda:InvokeFunction \
# --principal s3.amazonaws.com \
# --source-arn arn:aws:s3:::akane-evidence-bucket
# -----------------------------------------------
# Create an EventBridge schedule rule
# -----------------------------------------------
# aws events put-rule \
# --name {rule-name} \
# --schedule-expression {schedule-expression} \
# --state ENABLED
# → Creates a scheduled execution rule in EventBridge
# cron expression: cron(minute hour day month weekday year)
# rate expression: rate(value unit) [unit: minutes / hours / days]
# Example: aws events put-rule \
# --name kogami-daily-patrol \
# --schedule-expression "cron(0 9 * * ? *)" \
# --state ENABLED
# -----------------------------------------------
# Register a Lambda function as an EventBridge target
# -----------------------------------------------
# aws events put-targets \
# --rule {rule-name} \
# --targets "Id={target-ID},Arn={Lambda-function-ARN}"
# → Registers a Lambda function as the target for an EventBridge rule
# Example: aws events put-targets \
# --rule kogami-daily-patrol \
# --targets "Id=kogami-target,Arn=arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func"
Trigger Overview
| Trigger | Invocation Model | Description |
|---|---|---|
| S3 | Asynchronous | Invokes Lambda on events such as object uploads or deletions to a bucket. Commonly used for image resizing and log processing. |
| API Gateway | Synchronous | Invokes Lambda on HTTP/HTTPS requests and returns a response. Supports both REST APIs and WebSocket APIs. |
| EventBridge (CloudWatch Events) | Asynchronous | Invokes Lambda on a cron or rate schedule, or when an event from an AWS service matches a configured event pattern. |
| SQS | Polling (Asynchronous) | Lambda polls the SQS queue and processes messages when they arrive. You can configure a batch size to process multiple messages at once. |
| DynamoDB Streams | Polling (Synchronous) | Receives DynamoDB table changes (INSERT / MODIFY / REMOVE) via a stream and uses Lambda to perform downstream processing. |
| SNS | Asynchronous | Invokes Lambda when a message is published to an SNS topic. Supports fan-out delivery to multiple Lambda functions. |
| Kinesis Data Streams | Polling (Synchronous) | Polls records from a Kinesis stream and processes them with Lambda. Used for real-time log analysis and aggregation. |
| ALB (Application Load Balancer) | Synchronous | Registers Lambda as a target group of an ALB to handle HTTP/HTTPS requests with Lambda. |
| Command / Operation | Description |
|---|---|
aws s3api put-bucket-notification-configuration | Registers notification settings for an S3 bucket via a JSON file to configure Lambda as a trigger. |
aws lambda add-permission | Adds invocation permission to a Lambda function's resource-based policy for trigger source services such as S3 and API Gateway. |
aws lambda get-policy --function-name {function-name} | Displays the current resource-based policy configured for a Lambda function. |
aws events put-rule | Creates a schedule rule or event pattern rule in EventBridge. Specify a cron or rate expression with --schedule-expression. |
aws events put-targets | Registers a Lambda function as the target of an EventBridge rule. You can also transform event data using --input or --input-transformer. |
aws events list-rules | Lists the current EventBridge rules. |
aws events list-targets-by-rule --rule {rule-name} | Lists the targets registered for the specified rule. |
cron(minute hour day month weekday year) | Specifies a schedule using a cron expression in UTC. Day and weekday cannot both be non-*, so set one of them to ?. |
rate(value unit) | Specifies a fixed-interval schedule. Units can be minutes, hours, or days (e.g., rate(5 minutes)). |
Sample Code
# -----------------------------------------------
# Configure an S3 trigger on PSYCHO-PASS's
# evidence image bucket
# When Akane uploads an evidence file,
# akane-inspect-handler is invoked automatically
# -----------------------------------------------
# First, grant S3 permission to invoke the Lambda function
aws lambda add-permission \
--function-name akane-inspect-handler \
--statement-id s3-invoke-permission \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::akane-evidence-bucket \
--region ap-northeast-1
# Prepare the S3 notification configuration as a JSON file
cat > s3-notification.json << 'EOF'
{
"LambdaFunctionConfigurations": [
{
"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:akane-inspect-handler",
"Events": ["s3:ObjectCreated:*"],
"Filter": {
"Key": {
"FilterRules": [
{
"Name": "prefix",
"Value": "evidence/"
},
{
"Name": "suffix",
"Value": ".jpg"
}
]
}
}
}
]
}
EOF
# Register the trigger configuration on the S3 bucket
aws s3api put-bucket-notification-configuration \
--bucket akane-evidence-bucket \
--notification-configuration file://s3-notification.json \
--region ap-northeast-1
# Verify the configuration
aws s3api get-bucket-notification-configuration \
--bucket akane-evidence-bucket \
--region ap-northeast-1
$ aws lambda add-permission \
> --function-name akane-inspect-handler \
> --statement-id s3-invoke-permission \
> --action lambda:InvokeFunction \
> --principal s3.amazonaws.com \
> --source-arn arn:aws:s3:::akane-evidence-bucket \
> --region ap-northeast-1
{
"Statement": "{\"Sid\":\"s3-invoke-permission\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:111122223333:function:akane-inspect-handler\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:s3:::akane-evidence-bucket\"}}}"
}
$ aws s3api put-bucket-notification-configuration \
> --bucket akane-evidence-bucket \
> --notification-configuration file://s3-notification.json \
> --region ap-northeast-1
$ aws s3api get-bucket-notification-configuration \
> --bucket akane-evidence-bucket \
> --region ap-northeast-1
{
"LambdaFunctionConfigurations": [
{
"LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:akane-inspect-handler",
"Events": [
"s3:ObjectCreated:*"
],
"Filter": {
"Key": {
"FilterRules": [
{ "Name": "Prefix", "Value": "evidence/" },
{ "Name": "Suffix", "Value": ".jpg" }
]
}
}
}
]
}
# ----------------------------------------------- # Run Kogami's patrol function every day at # 09:00 UTC using an EventBridge schedule # ----------------------------------------------- # Create an EventBridge schedule rule (every day at 09:00 UTC) aws events put-rule \ --name kogami-daily-patrol \ --schedule-expression "cron(0 9 * * ? *)" \ --state ENABLED \ --description "Runs Kogami's patrol function every day at 09:00 UTC" \ --region ap-northeast-1 # Grant EventBridge permission to invoke the Lambda function aws lambda add-permission \ --function-name kogami-patrol-func \ --statement-id eventbridge-invoke-permission \ --action lambda:InvokeFunction \ --principal events.amazonaws.com \ --source-arn arn:aws:events:ap-northeast-1:111122223333:rule/kogami-daily-patrol \ --region ap-northeast-1 # Register the Lambda function as the target of the EventBridge rule aws events put-targets \ --rule kogami-daily-patrol \ --targets "Id=kogami-target,Arn=arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func" \ --region ap-northeast-1 # Verify that the rule was created aws events list-rules \ --name-prefix kogami \ --region ap-northeast-1 # Verify the targets aws events list-targets-by-rule \ --rule kogami-daily-patrol \ --region ap-northeast-1
$ aws events put-rule \
> --name kogami-daily-patrol \
> --schedule-expression "cron(0 9 * * ? *)" \
> --state ENABLED \
> --description "Runs Kogami's patrol function every day at 09:00 UTC" \
> --region ap-northeast-1
{
"RuleArn": "arn:aws:events:ap-northeast-1:111122223333:rule/kogami-daily-patrol"
}
$ aws lambda add-permission \
> --function-name kogami-patrol-func \
> --statement-id eventbridge-invoke-permission \
> --action lambda:InvokeFunction \
> --principal events.amazonaws.com \
> --source-arn arn:aws:events:ap-northeast-1:111122223333:rule/kogami-daily-patrol \
> --region ap-northeast-1
{
"Statement": "{\"Sid\":\"eventbridge-invoke-permission\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func\"}"
}
$ aws events put-targets \
> --rule kogami-daily-patrol \
> --targets "Id=kogami-target,Arn=arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func" \
> --region ap-northeast-1
{
"FailedEntryCount": 0,
"FailedEntries": []
}
$ aws events list-rules \
> --name-prefix kogami \
> --region ap-northeast-1
{
"Rules": [
{
"Name": "kogami-daily-patrol",
"Arn": "arn:aws:events:ap-northeast-1:111122223333:rule/kogami-daily-patrol",
"State": "ENABLED",
"Description": "Runs Kogami's patrol function every day at 09:00 UTC",
"ScheduleExpression": "cron(0 9 * * ? *)"
}
]
}
$ aws events list-targets-by-rule \
> --rule kogami-daily-patrol \
> --region ap-northeast-1
{
"Targets": [
{
"Id": "kogami-target",
"Arn": "arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func"
}
]
}
# -----------------------------------------------
# Run Ginoza's weekly report function every
# Monday at 18:00 UTC. Pass custom JSON with --input
# -----------------------------------------------
# Create a weekly schedule rule (every Monday at 18:00 UTC)
aws events put-rule \
--name ginoza-weekly-report \
--schedule-expression "cron(0 18 ? * MON *)" \
--state ENABLED \
--region ap-northeast-1
# Grant EventBridge permission to invoke the Lambda function
aws lambda add-permission \
--function-name ginoza-report-func \
--statement-id eventbridge-weekly-permission \
--action lambda:InvokeFunction \
--principal events.amazonaws.com \
--source-arn arn:aws:events:ap-northeast-1:111122223333:rule/ginoza-weekly-report \
--region ap-northeast-1
# Register the target with a custom input JSON
aws events put-targets \
--rule ginoza-weekly-report \
--targets '[
{
"Id": "ginoza-target",
"Arn": "arn:aws:lambda:ap-northeast-1:111122223333:function:ginoza-report-func",
"Input": "{\"reporter\":\"Ginoza\",\"report_type\":\"weekly\",\"division\":\"CID\"}"
}
]' \
--region ap-northeast-1
$ aws events put-rule \
> --name ginoza-weekly-report \
> --schedule-expression "cron(0 18 ? * MON *)" \
> --state ENABLED \
> --region ap-northeast-1
{
"RuleArn": "arn:aws:events:ap-northeast-1:111122223333:rule/ginoza-weekly-report"
}
$ aws events put-targets \
> --rule ginoza-weekly-report \
> --targets '[...]' \
> --region ap-northeast-1
{
"FailedEntryCount": 0,
"FailedEntries": []
}
$ aws lambda invoke \
> --function-name ginoza-report-func \
> --cli-binary-format raw-in-base64-out \
> --payload '{"reporter":"Ginoza","report_type":"weekly","division":"CID"}' \
> --region ap-northeast-1 \
> response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
$ cat response.json
{"statusCode": 200, "body": "{\"reporter\": \"Ginoza\", \"report_type\": \"weekly\", \"generated\": true}"}
# -----------------------------------------------
# Connect Shusei's analysis API to Lambda
# via API Gateway
# Grant the resource-based policy for
# API Gateway to invoke the function
# -----------------------------------------------
# Note the API Gateway stage ARN format:
# arn:aws:execute-api:{region}:{account-id}:{API_ID}/{stage}/{method}/{resource}
API_ID="abc1def2gh"
# Grant API Gateway permission to invoke the Lambda function
aws lambda add-permission \
--function-name shusei-analysis-func \
--statement-id apigateway-invoke-permission \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:ap-northeast-1:111122223333:${API_ID}/prod/POST/analyze" \
--region ap-northeast-1
# Verify the configured resource-based policy
aws lambda get-policy \
--function-name shusei-analysis-func \
--region ap-northeast-1 \
--query 'Policy' \
--output text | python3 -m json.tool
$ API_ID="abc1def2gh"
$ aws lambda add-permission \
> --function-name shusei-analysis-func \
> --statement-id apigateway-invoke-permission \
> --action lambda:InvokeFunction \
> --principal apigateway.amazonaws.com \
> --source-arn "arn:aws:execute-api:ap-northeast-1:111122223333:abc1def2gh/prod/POST/analyze" \
> --region ap-northeast-1
{
"Statement": "{\"Sid\":\"apigateway-invoke-permission\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:ap-northeast-1:111122223333:function:shusei-analysis-func\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1:111122223333:abc1def2gh/prod/POST/analyze\"}}}"
}
$ aws lambda get-policy \
> --function-name shusei-analysis-func \
> --region ap-northeast-1 \
> --query 'Policy' \
> --output text | python3 -m json.tool
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "apigateway-invoke-permission",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:111122223333:function:shusei-analysis-func",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:ap-northeast-1:111122223333:abc1def2gh/prod/POST/analyze"
}
}
}
]
}
# -----------------------------------------------
# Configure an SQS queue as a trigger for
# Yayoi's notification processing function
# Lambda polls SQS and batch-processes messages
# -----------------------------------------------
# Get the SQS queue ARN
aws sqs get-queue-attributes \
--queue-url https://sqs.ap-northeast-1.amazonaws.com/111122223333/yayoi-notification-queue \
--attribute-names QueueArn \
--region ap-northeast-1
# Create an SQS event source mapping for Lambda
# Note: SQS triggers are configured with create-event-source-mapping,
# not with add-permission
aws lambda create-event-source-mapping \
--function-name yayoi-notification-func \
--event-source-arn arn:aws:sqs:ap-northeast-1:111122223333:yayoi-notification-queue \
--batch-size 10 \
--enabled \
--region ap-northeast-1
# Verify the event source mapping list
aws lambda list-event-source-mappings \
--function-name yayoi-notification-func \
--region ap-northeast-1 \
--query 'EventSourceMappings[*].{UUID:UUID,Source:EventSourceArn,State:State,BatchSize:BatchSize}'
$ aws sqs get-queue-attributes \
> --queue-url https://sqs.ap-northeast-1.amazonaws.com/111122223333/yayoi-notification-queue \
> --attribute-names QueueArn \
> --region ap-northeast-1
{
"Attributes": {
"QueueArn": "arn:aws:sqs:ap-northeast-1:111122223333:yayoi-notification-queue"
}
}
$ aws lambda create-event-source-mapping \
> --function-name yayoi-notification-func \
> --event-source-arn arn:aws:sqs:ap-northeast-1:111122223333:yayoi-notification-queue \
> --batch-size 10 \
> --enabled \
> --region ap-northeast-1
{
"UUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"BatchSize": 10,
"EventSourceArn": "arn:aws:sqs:ap-northeast-1:111122223333:yayoi-notification-queue",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:yayoi-notification-func",
"LastModified": "2026-03-26T12:00:00.000+0000",
"State": "Creating",
"StateTransitionReason": "USER_INITIATED"
}
$ aws lambda list-event-source-mappings \
> --function-name yayoi-notification-func \
> --region ap-northeast-1 \
> --query 'EventSourceMappings[*].{UUID:UUID,Source:EventSourceArn,State:State,BatchSize:BatchSize}'
[
{
"UUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"Source": "arn:aws:sqs:ap-northeast-1:111122223333:yayoi-notification-queue",
"State": "Enabled",
"BatchSize": 10
}
]
Common Mistakes
Mistake 1: Missing resource-based policy causes EventBridge or S3 invocations to fail
To invoke Lambda from EventBridge, S3, API Gateway, or similar services, the Lambda function's resource-based policy must grant invocation permission to the trigger source service. Without the policy, even a correctly configured trigger will not execute the function.
# Less common approach: registering an EventBridge target without running add-permission first aws events put-targets \ --rule kogami-daily-patrol \ --targets "Id=kogami-target,Arn=arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func" # → The target registers successfully, but an AccessDeniedException occurs at runtime
Set up the resource-based policy with aws lambda add-permission before registering the target.
# Common approach: grant invocation permission with add-permission before registering the target aws lambda add-permission \ --function-name kogami-patrol-func \ --statement-id eventbridge-invoke-permission \ --action lambda:InvokeFunction \ --principal events.amazonaws.com \ --source-arn arn:aws:events:ap-northeast-1:111122223333:rule/kogami-daily-patrol \ --region ap-northeast-1 aws events put-targets \ --rule kogami-daily-patrol \ --targets "Id=kogami-target,Arn=arn:aws:lambda:ap-northeast-1:111122223333:function:kogami-patrol-func" \ --region ap-northeast-1
Mistake 2: Forgetting that EventBridge cron expressions use UTC, causing off-by-hours execution
EventBridge cron expressions are in UTC. If you want to schedule a function at a specific time in JST (Japan Standard Time), you must convert the time to UTC (JST minus 9 hours).
# Less common approach: specifying 18:00 intending JST but writing it as UTC 18:00 aws events put-rule \ --name ginoza-weekly-report \ --schedule-expression "cron(0 18 ? * MON *)" \ --state ENABLED # → In JST this means 27:00 (next day 03:00), not 18:00 JST
JST 18:00 is UTC 09:00. Convert from JST to UTC before writing the cron expression.
# Common approach: convert JST 18:00 to UTC 09:00 and specify that in the expression aws events put-rule \ --name ginoza-weekly-report \ --schedule-expression "cron(0 9 ? * MON *)" \ --state ENABLED # → Runs every Monday at 18:00 JST
Mistake 3: Missing S3 trigger filter causes Lambda infinite recursion
If Lambda processes an ObjectCreated event from an S3 bucket and writes the result back to the same bucket, an infinite loop occurs: Lambda writes to S3, which triggers Lambda again, which writes to S3, and so on.
# Less common approach: setting a trigger with no filter when input and output share the same bucket
# Contents of s3-notification.json (no filter):
# {
# "LambdaFunctionConfigurations": [{
# "LambdaFunctionArn": "...:function:akane-inspect-handler",
# "Events": ["s3:ObjectCreated:*"]
# }]
# }
aws s3api put-bucket-notification-configuration \
--bucket akane-evidence-bucket \
--notification-configuration file://s3-notification.json
# → Every write by Lambda fires the trigger again, causing infinite recursion
Use different prefixes or suffixes for input and output files and configure a filter on the trigger. Alternatively, use separate buckets for input and output to prevent recursion.
# Common approach: trigger only on files under input/ prefix to prevent recursion
# Contents of s3-notification-filtered.json:
# {
# "LambdaFunctionConfigurations": [{
# "LambdaFunctionArn": "...:function:akane-inspect-handler",
# "Events": ["s3:ObjectCreated:*"],
# "Filter": {
# "Key": {
# "FilterRules": [{"Name": "prefix", "Value": "input/"}]
# }
# }
# }]
# }
aws s3api put-bucket-notification-configuration \
--bucket akane-evidence-bucket \
--notification-configuration file://s3-notification-filtered.json
# → Only files under input/ trigger the function; writes to output/ are ignored
Summary
Lambda triggers fall into three broad invocation models. Synchronous invocation (API Gateway, ALB, etc.) returns a response to the request; the caller handles retries on error. Asynchronous invocation (S3, SNS, EventBridge, etc.) queues the event for Lambda to process; on failure, Lambda automatically retries up to two times. Polling (streams/queues) (SQS, DynamoDB Streams, Kinesis, etc.) means Lambda polls the event source for data; configure this with aws lambda create-event-source-mapping. Setting up an S3 trigger requires both aws s3api put-bucket-notification-configuration and aws lambda add-permission. For EventBridge scheduled execution, create a rule with aws events put-rule and register Lambda as the target with aws events put-targets. Cron expressions must be written in UTC; when day and weekday are both specified, one of them must be set to ?. See also Creating and Deploying Lambda Functions and Lambda Overview and Basic Operations.
If you find any errors or copyright issues, please contact us.