EventBridge cron rules are how you get your AWS infrastructure to do things on a schedule, but they’re not just for setting a clock; they’re really about orchestrating asynchronous state changes across distributed systems.
Let’s see it in action. Imagine we have a service that needs to process a batch of data every hour. We’ll use EventBridge to trigger an ECS task.
First, we need an EventBridge rule. This rule will have a cron expression that defines the schedule.
{
"Name": "hourly-data-processor-rule",
"ScheduleExpression": "cron(0 * * * ? *)",
"State": "ENABLED",
"Description": "Triggers the data processing task every hour on the hour."
}
The cron(0 * * * ? *) expression means: at minute 0, of every hour, of every day, of every month, any day of the week, in the UTC timezone.
Next, this rule needs a target. Our target will be an ECS task. When the rule triggers, EventBridge will send an event that tells ECS to run a specific task definition.
The target configuration in EventBridge looks something like this:
{
"Id": "ecs-task-target",
"Arn": "arn:aws:ecs:us-east-1:123456789012:cluster/my-ecs-cluster",
"RoleArn": "arn:aws:iam::123456789012:role/EventBridgeEcsTaskRole",
"EcsParameters": {
"TaskDefinitionArn": "arn:aws:ecs:us-east-1:123456789012:task-definition/my-data-processor-task:1",
"TaskCount": 1,
"LaunchType": "FARGATE",
"NetworkConfiguration": {
"AwsVpcConfiguration": {
"Subnets": ["subnet-012345abcdef67890", "subnet-098765fedcba01234"],
"SecurityGroups": ["sg-012345abcdef67890"],
"AssignPublicIp": "ENABLED"
}
}
}
}
Here, Arn is our ECS cluster ARN, RoleArn is the IAM role EventBridge assumes to interact with ECS, and EcsParameters specifies the task definition to run, the launch type (Fargate or EC2), and networking details for Fargate tasks. The TaskCount is set to 1, meaning one instance of the task will be launched.
The EventBridgeEcsTaskRole needs permissions to run ECS tasks. A minimal policy would look like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:RunTask"
],
"Resource": "arn:aws:ecs:us-east-1:123456789012:task-definition/my-data-processor-task:1",
"Condition": {
"ArnLike": {
"ecs:cluster": "arn:aws:ecs:us-east-1:123456789012:cluster/my-ecs-cluster"
}
}
},
{
"Effect": "Allow",
"Action": [
"ecs:DescribeTasks"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole"
}
]
}
The iam:PassRole permission is crucial because when ecs:RunTask is called, ECS needs to assume the ecsTaskExecutionRole for its own operations (like pulling images from ECR). This statement allows EventBridge to pass that role to ECS.
The ecsTaskExecutionRole itself needs permissions for ECS to pull container images and to send logs to CloudWatch Logs.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
The core problem EventBridge cron rules solve is decoupling the when from the what. You define the schedule in EventBridge, and it reliably triggers an action in another AWS service without you needing to manage a server or a cron daemon. It’s all managed AWS infrastructure. The actual task execution, its resources, and its logic are defined entirely within the ECS task definition and its associated IAM roles.
One of the most common points of confusion is the timezone for cron expressions. AWS EventBridge uses UTC for all cron expressions. If you need to schedule something for 9 AM Pacific Time (which is PST/PDT), you must translate that to UTC. For example, 9 AM PST (UTC-8) is 5 PM UTC, so the expression would be cron(0 17 ? * MON-FRI *). Similarly, 9 AM PDT (UTC-7) is 4 PM UTC, so cron(0 16 ? * MON-FRI *). Always double-check your timezones.
The next thing you’ll likely encounter is handling idempotency and retries for your scheduled tasks, especially if the task can fail and EventBridge needs to re-trigger it.