Scheduling Lambda with EventBridge: Cron Expressions and Daily Triggers Explained
Triggering a Lambda function on a fixed schedule — say, every day at 8 AM UTC — is one of the most common serverless patterns, yet the permission model and cron syntax trip up engineers more often than the wiring itself. This post covers how scheduling Lambda with EventBridge works end-to-end, including the exact cron format, the resource-based policy that actually grants invocation rights, and the CLI commands to verify everything is wired correctly.
TL;DR: Scheduling Lambda with EventBridge
| Concern | Answer |
|---|---|
| Trigger mechanism | EventBridge Scheduler rule with a schedule expression |
| Cron format | cron(Minutes Hours Day-of-month Month Day-of-week Year) — 6 fields, UTC only |
| Daily 8 AM expression | cron(0 8 * * ? *) |
| Required permission | Lambda resource-based policy granting lambda:InvokeFunction to events.amazonaws.com |
| IAM execution role | Not required on the EventBridge rule itself for Lambda targets — the resource-based policy is sufficient |
| Time zone | Schedule expressions in EventBridge rules use UTC |
How EventBridge Scheduled Rules Work
EventBridge rules with a schedule expression act as a managed cron daemon inside AWS. At the configured time, the EventBridge service itself calls lambda:InvokeFunction on your function. Because EventBridge is invoking Lambda directly — not assuming a role in your account — the permission gate is the Lambda resource-based policy, not an IAM execution role attached to the rule. This is the single most common misunderstanding: engineers attach an IAM role to the rule expecting it to unlock invocation, but for Lambda targets, the resource-based policy on the function is what EventBridge checks.
- EventBridge evaluates the schedule — at the configured UTC time, the service triggers the rule.
- EventBridge calls Lambda directly — it invokes the target function using its own service principal (
events.amazonaws.com). - Lambda checks the resource-based policy — if the policy grants
lambda:InvokeFunctiontoevents.amazonaws.comwith the correct rule ARN as a condition, the invocation proceeds. - Lambda executes using its execution role — the function's own IAM execution role governs what AWS APIs the function code can call.
EventBridge Cron Expression Syntax
EventBridge schedule expressions support two formats: rate(value unit) for simple intervals and cron(...) for calendar-based schedules. The cron format is not identical to standard Unix cron — it has six fields and requires a ? wildcard in either the day-of-month or day-of-week field when the other is specified.
cron(Minutes Hours Day-of-month Month Day-of-week Year)
Field Values Wildcards allowed
------ ------ -----------------
Minutes 0-59 , - * /
Hours 0-23 , - * /
Day-of-month 1-31 , - * ? / L W
Month 1-12 or JAN-DEC , - * /
Day-of-week 1-7 or SUN-SAT , - * ? L #
Year 1970-2199 , - * /
The ? wildcard means "no specific value" and is required in exactly one of day-of-month or day-of-week — you cannot specify both simultaneously. This differs from standard cron where * fills both freely.
Common Schedule Expressions
| Intent | Expression |
|---|---|
| Every day at 8:00 AM UTC | cron(0 8 * * ? *) |
| Every weekday at 9:00 AM UTC | cron(0 9 ? * MON-FRI *) |
| First day of every month at midnight UTC | cron(0 0 1 * ? *) |
| Every 15 minutes | rate(15 minutes) |
| Every hour | rate(1 hour) |
Think of the ? wildcard as a mutual exclusion lock: day-of-month and day-of-week compete for the same calendar dimension. AWS requires you to explicitly yield one of them rather than silently ignoring the conflict.
Step 1: Create the EventBridge Scheduled Rule
Before creating the rule, confirm your Lambda function exists and note its ARN. The rule and the function must be in the same AWS region — EventBridge rules are regional resources.
aws events put-rule \
--name "DailyLambdaTrigger" \
--schedule-expression "cron(0 8 * * ? *)" \
--state ENABLED \
--region us-east-1
This creates the rule in a disabled-until-enabled state with the schedule expression. The command returns the rule ARN — save it, because you need it when adding the target and when scoping the Lambda permission.
# Verify the rule was created correctly
aws events describe-rule \
--name "DailyLambdaTrigger" \
--region us-east-1
Step 2: Add the Lambda Function as a Target
A rule without a target does nothing. The target wires the rule to your specific Lambda function. The --targets parameter requires an Id (a unique string within the rule, not a global identifier) and the function ARN.
aws events put-targets \
--rule "DailyLambdaTrigger" \
--targets "Id=DailyLambdaTarget,Arn=arn:aws:lambda:us-east-1:123456789012:function:MyScheduledFunction" \
--region us-east-1
If the command returns a FailedEntryCount greater than zero, inspect the FailedEntries array in the response — it will identify whether the issue is a malformed ARN or a missing permission.
Step 3: Grant EventBridge Permission to Invoke Lambda
This is the step most engineers skip when wiring things manually. EventBridge invokes Lambda using its own service principal. Without a resource-based policy on the function explicitly allowing this, every scheduled invocation will be silently dropped — no error surfaces in EventBridge, and no invocation record appears in Lambda.
aws lambda add-permission \
--function-name MyScheduledFunction \
--statement-id "AllowEventBridgeDailyTrigger" \
--action "lambda:InvokeFunction" \
--principal "events.amazonaws.com" \
--source-arn "arn:aws:events:us-east-1:123456789012:rule/DailyLambdaTrigger" \
--region us-east-1
The --source-arn condition scopes the permission to this specific rule. Without it, any EventBridge rule in your account could invoke this function — a broader permission than most workloads require.
# Verify the resource-based policy was applied
aws lambda get-policy \
--function-name MyScheduledFunction \
--region us-east-1
The output is a JSON string. Confirm the Principal is events.amazonaws.com, the Action is lambda:InvokeFunction, and the Condition contains your rule ARN under ArnLike.
but Lambda never runs?"] --> B{"Check: aws lambda get-policy"} B -->|"Policy missing"| C["Add resource-based policy
aws lambda add-permission"] B -->|"Policy exists"| D{"Check source-arn condition"} D -->|"ARN mismatch"| E["Remove statement
Re-add with correct rule ARN"] D -->|"ARN correct"| F{"Check rule target ARN"} F -->|"Target ARN wrong"| G["Update target via
aws events put-targets"] F -->|"Target ARN correct"| H["Check Lambda execution role
for code-level errors in CWL"]
Step 4: Verify End-to-End Invocation
Rather than waiting until 8 AM to discover a misconfiguration, force a test invocation immediately. This confirms the permission model is correct independent of the schedule.
# Manually invoke the function to confirm execution role and code are healthy
aws lambda invoke \
--function-name MyScheduledFunction \
--payload '{}' \
--cli-binary-format raw-in-base64-out \
response.json \
--region us-east-1
cat response.json
A manual invocation bypasses EventBridge entirely — it calls Lambda directly using your IAM credentials. If this succeeds but the scheduled invocation does not, the problem is isolated to the resource-based policy or the rule target configuration, not the function itself.
# Check recent Lambda invocation metrics to confirm scheduled runs are occurring
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name Invocations \
--dimensions Name=FunctionName,Value=MyScheduledFunction \
--start-time 2024-01-15T07:00:00Z \
--end-time 2024-01-15T09:00:00Z \
--period 3600 \
--statistics Sum \
--region us-east-1
Scheduling Lambda with EventBridge: Diagnosing Silent Failures
The failure pattern that burns engineers most: the rule shows as ENABLED in the console, the target is listed, but Lambda never executes. The instinct is to check the Lambda execution role — adding more permissions, attaching policies. None of it helps, because the execution role is irrelevant to whether EventBridge can invoke the function.
The actual cause: the resource-based policy was never added, or was added with a mismatched rule ARN. EventBridge silently drops the invocation when the policy check fails. There is no EventBridge error log for this condition under standard rule configurations.
The fix is always the same: run aws lambda get-policy and verify the statement exists with the correct principal and source ARN condition. If the policy is absent, add it with aws lambda add-permission as shown in Step 3. If the ARN in the condition doesn't match the actual rule ARN, remove the statement and re-add it with the correct value.
# Remove an incorrect permission statement before re-adding
aws lambda remove-permission \
--function-name MyScheduledFunction \
--statement-id "AllowEventBridgeDailyTrigger" \
--region us-east-1
One non-obvious interaction: if you delete and recreate a rule with the same name, the rule ARN remains the same — but if you created the rule in a different account or region by mistake, the ARN in the policy condition will never match. Always confirm the region in both the rule ARN and the Lambda ARN are identical.
IAM Least Privilege for the Lambda Execution Role
The Lambda execution role governs what the function code can do after it starts — not whether EventBridge can start it. At minimum, the execution role needs permission to write logs to CloudWatch Logs. Any additional permissions depend entirely on what your function does.
🔽 Click to expand: Minimal Lambda execution role policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/MyScheduledFunction:*"
}
]
}
The trust policy for the execution role must allow lambda.amazonaws.com to assume it — this is separate from the resource-based policy that allows EventBridge to invoke the function.
🔽 Click to expand: Lambda execution role trust policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Wrap-Up and Next Steps for Scheduling Lambda with EventBridge
Scheduling Lambda with EventBridge requires three correctly wired components: a rule with a valid schedule expression, a target pointing to the function ARN, and a Lambda resource-based policy granting lambda:InvokeFunction to events.amazonaws.com. The resource-based policy is the only permission gate EventBridge checks for Lambda targets — no IAM role on the rule is needed for this integration.
- Review the EventBridge schedule expression reference for the full cron field specification.
- For more complex scheduling needs — including time zone support and one-time schedules — evaluate Amazon EventBridge Scheduler, which is a separate service from EventBridge rules.
- Enable Lambda CloudWatch Logs before deploying to production so invocation failures surface immediately.
Glossary
| Term | Definition |
|---|---|
| Schedule Expression | A cron(...) or rate(...) string that defines when an EventBridge rule fires. |
| Resource-Based Policy | A policy attached directly to a Lambda function that controls which principals can invoke it. |
| Service Principal | An identifier (e.g., events.amazonaws.com) representing an AWS service in IAM policy statements. |
| Execution Role | The IAM role assumed by Lambda during function execution, governing what AWS APIs the function code can call. |
| EventBridge Rule Target | The AWS resource (e.g., a Lambda function ARN) that EventBridge invokes when a rule matches. |
Comments
Post a Comment