Scheduling AWS Lambda with EventBridge: Cron & Rate Expressions Explained
A common operational need — running a Lambda function at a fixed time every day, like 8 AM for a daily report — requires a reliable scheduler. Amazon EventBridge (formerly CloudWatch Events) provides exactly this via managed, serverless scheduling with both cron and rate expressions.
TL;DR
| Requirement | Expression Type | Example |
|---|---|---|
| Every day at 8 AM UTC | Cron | cron(0 8 * * ? *) |
| Every 5 minutes | Rate | rate(5 minutes) |
| Every 1 hour | Rate | rate(1 hour) |
| Weekdays at 9 AM UTC | Cron | cron(0 9 ? * MON-FRI *) |
| First day of month at midnight | Cron | cron(0 0 1 * ? *) |
Architecture Overview
The flow is straightforward: EventBridge evaluates the schedule expression, fires an event at the defined interval, and invokes your Lambda function as the target. No polling, no infrastructure to manage.
cron(0 8 * * ? *)"] Bus["Default Event Bus"] Lambda["AWS Lambda
MyDailyReportFunction"] CW["CloudWatch Logs
/aws/lambda/..."] DLQ["SQS Dead Letter Queue"] EB -->|"Fires at 8 AM UTC"| Bus Bus -->|"Async Invoke"| Lambda Lambda -->|"Execution Logs"| CW Lambda -->|"On Failure (retries exhausted)"| DLQ
- EventBridge Scheduler: Holds the cron or rate rule and evaluates it against UTC time.
- Event Bus (default): The rule fires an event onto the default event bus at the scheduled time.
- Lambda Target: EventBridge invokes the Lambda function asynchronously, passing a JSON event payload.
- Execution Role: EventBridge requires a resource-based policy on the Lambda function granting
lambda:InvokeFunctionpermission to the EventBridge service principal.
Analogy: Think of EventBridge as a corporate calendar system. You set a recurring meeting (the rule). At the scheduled time, the calendar automatically sends an invite (the event) to the attendee (Lambda). Lambda doesn't sit waiting — it only activates when the invite arrives.
Cron Expression Syntax (EventBridge-Specific)
EventBridge cron expressions use 6 fields, unlike the standard 5-field Unix cron. The fields are positional and strictly ordered.
| Position | Field | Allowed Values | Wildcards |
|---|---|---|---|
| 1 | Minutes | 0–59 | , - * / |
| 2 | Hours | 0–23 | , - * / |
| 3 | Day-of-month | 1–31 | , - * ? / L W |
| 4 | Month | 1–12 or JAN–DEC | , - * / |
| 5 | Day-of-week | 1–7 or SUN–SAT | , - * ? L # |
| 6 | Year | 1970–2199 | , - * / |
Critical Rule: You cannot specify a value for both Day-of-month and Day-of-week simultaneously. One of them must be ? (no specific value). This is an EventBridge-specific constraint not present in standard Unix cron.
Common Cron Examples
# Every day at 8:00 AM UTC
cron(0 8 * * ? *)
# Every Monday at 9:00 AM UTC
cron(0 9 ? * MON *)
# Every weekday (Mon-Fri) at 6:00 PM UTC
cron(0 18 ? * MON-FRI *)
# Every 15 minutes
cron(0/15 * * * ? *)
# First day of every month at midnight UTC
cron(0 0 1 * ? *)
Rate Expression Syntax
Rate expressions are simpler and ideal for fixed intervals. The syntax is rate(value unit).
| Unit | Singular | Plural |
|---|---|---|
| Minutes | rate(1 minute) | rate(5 minutes) |
| Hours | rate(1 hour) | rate(2 hours) |
| Days | rate(1 day) | rate(7 days) |
Both singular and plural unit forms are accepted by AWS. rate(1 hour) and rate(1 hours) are both valid per AWS documentation. Rate expressions always run relative to when the rule was created or last updated — they do not align to clock boundaries.
Implementation: Step-by-Step
Step 1 — Grant EventBridge Permission to Invoke Lambda
EventBridge invokes Lambda using a resource-based policy. You must add a permission statement to your Lambda function allowing the EventBridge service principal to call it.
aws lambda add-permission \
--function-name MyDailyReportFunction \
--statement-id EventBridgeDailyTrigger \
--action lambda:InvokeFunction \
--principal events.amazonaws.com \
--source-arn arn:aws:events:us-east-1:123456789012:rule/DailyReportRule
Step 2 — Create the EventBridge Rule
aws events put-rule \
--name DailyReportRule \
--schedule-expression "cron(0 8 * * ? *)" \
--state ENABLED \
--description "Triggers Lambda every day at 8 AM UTC"
Step 3 — Add Lambda as the Target
🔽 [Click to expand] — Full put-targets command with input transformer
aws events put-targets \
--rule DailyReportRule \
--targets "[
{
\"Id\": \"DailyReportLambdaTarget\",
\"Arn\": \"arn:aws:lambda:us-east-1:123456789012:function:MyDailyReportFunction\",
\"Input\": \"{\\\"source\\\": \\\"eventbridge-scheduler\\\", \\\"task\\\": \\\"daily-report\\\"}\"
}
]"
Step 4 — Verify the Rule
aws events describe-rule --name DailyReportRule
CloudFormation / IaC Definition
🔽 [Click to expand] — CloudFormation YAML template
AWSTemplateFormatVersion: '2010-09-09'
Description: EventBridge rule to trigger Lambda daily at 8 AM UTC
Resources:
DailyReportRule:
Type: AWS::Events::Rule
Properties:
Name: DailyReportRule
Description: Triggers Lambda every day at 8 AM UTC
ScheduleExpression: "cron(0 8 * * ? *)"
State: ENABLED
Targets:
- Id: DailyReportLambdaTarget
Arn: !GetAtt MyDailyReportFunction.Arn
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref MyDailyReportFunction
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt DailyReportRule.Arn
MyDailyReportFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: MyDailyReportFunction
Runtime: python3.12
Handler: index.handler
Role: arn:aws:iam::123456789012:role/LambdaExecutionRole
Code:
ZipFile: |
def handler(event, context):
print("Daily report triggered:", event)
return {"status": "ok"}
Execution Flow Deep-Dive
- Schedule Evaluation: EventBridge evaluates the cron expression against UTC. All EventBridge schedules run in UTC — there is no native timezone offset in EventBridge Rules (note: EventBridge Scheduler, a separate newer service, does support timezones).
- Asynchronous Invocation: EventBridge invokes Lambda asynchronously. Lambda queues the event internally and returns a 200 immediately to EventBridge.
- Retry Behavior: On Lambda-side failures, Lambda's asynchronous invocation retry policy applies (up to 2 retries by default). EventBridge itself does not retry failed Lambda invocations.
- Dead Letter Queue: Configure a Lambda DLQ (SQS or SNS) to capture events that exhaust retries.
- CloudWatch Logs: Lambda execution logs are written to CloudWatch Logs under
/aws/lambda/MyDailyReportFunction.
EventBridge Rules vs. EventBridge Scheduler
AWS offers two scheduling mechanisms. Understanding the distinction prevents architectural mismatches.
| Feature | EventBridge Rules (Scheduled) | EventBridge Scheduler |
|---|---|---|
| Timezone support | UTC only | Named timezones supported |
| One-time schedules | Not supported | Supported |
| Flexible time windows | Not supported | Supported |
| Scale | Tied to event bus limits | Designed for high-volume schedules |
| Use case | Simple recurring triggers | Complex, high-scale, or timezone-aware scheduling |
Common Pitfalls
| Pitfall | Root Cause | Fix |
|---|---|---|
| Lambda never triggers | Missing resource-based policy on Lambda | Add lambda:InvokeFunction permission for events.amazonaws.com |
| Wrong execution time | Confusing local time with UTC | EventBridge Rules always use UTC; convert your target time to UTC explicitly |
| Cron expression rejected | Both Day-of-month and Day-of-week are set | Set one field to ? — e.g., cron(0 8 * * ? *) |
| Silent failures | No DLQ configured on Lambda async invocation | Configure an SQS DLQ on the Lambda function's event invoke config |
| Timezone mismatch | EventBridge Rules have no timezone parameter | Use EventBridge Scheduler if you need named timezone support |
IAM Least Privilege Reference
The Lambda execution role does not need EventBridge permissions. The trust relationship flows in one direction: EventBridge → Lambda. The only required permission is the Lambda resource-based policy shown in Step 1. If you are creating rules programmatically, the IAM identity needs events:PutRule, events:PutTargets, and lambda:AddPermission.
Wrap-Up & Next Steps
For a daily 8 AM trigger, cron(0 8 * * ? *) on an EventBridge Rule is the correct, minimal solution. If you need timezone-aware scheduling, one-time executions, or flexible time windows, migrate to EventBridge Scheduler. Always validate your cron expressions using the AWS Console's built-in schedule preview before deploying to production.
- 📖 AWS Docs: Schedule expressions for rules
- 📖 AWS Docs: EventBridge Scheduler
- 📖 AWS Docs: Asynchronous Lambda invocation
Glossary
| Term | Definition |
|---|---|
| EventBridge Rule | An AWS resource that matches incoming events or fires on a schedule, routing them to one or more targets. |
| Cron Expression | A 6-field time pattern (EventBridge-specific) defining when a scheduled rule fires, always evaluated in UTC. |
| Rate Expression | A simple interval-based schedule syntax (rate(value unit)) that fires at a fixed frequency. |
| Resource-Based Policy | A Lambda permission statement that grants an external service (like EventBridge) the right to invoke the function. |
| Asynchronous Invocation | A Lambda invocation mode where the caller (EventBridge) does not wait for the function to complete; Lambda queues and processes the event independently. |
Comments
Post a Comment