ECS Scheduled Task Not Running: the Two Metrics That Say Where It Failed, the Execution Role (RunTask + PassRole), Fargate Network Settings, Cron and Time Zones, the DLQ and the EC2 Placement Trap
An ECS scheduled task that is not running fails at one of three places, and the first job is to find out which: the schedule never fired, the schedule fired but ECS refused the RunTask call, or ECS launched the task and the task stopped seconds later. One CloudWatch metric separates them. In the AWS/Scheduler namespace, InvocationAttemptCount at zero means the schedule did not fire (disabled, a six-field cron expression with the wrong ?, a time zone surprise, or an end date in the past); TargetErrorCount above zero means ECS threw the call back (almost always the execution role missing ecs:RunTask or iam:PassRole, or a Fargate target with no network configuration); and attempts without errors and still no task means the task started and died, which the Stopped tasks list explains (ResourceInitializationError, CannotPullContainerError, or an exit code). Here is the one that fools everybody: ECS reports placement failures inside a successful RunTask response, so a schedule aimed at an EC2 cluster with no free instance shows zero errors and launches nothing. Below: the three-way diagnosis in order, the exact execution role, the Fargate network settings that make tasks die quietly, the cron and time zone rules, the dead-letter queue that tells you the real error, and the legacy EventBridge rule version with its own role and metric.
The shop's nightly report is an ECS task that runs at 2 a.m. and emails the day's bookings. Ethan built it as an EventBridge Scheduler schedule on Monday, saw a task run when he pressed "run once," and went home. By Thursday there had been no reports. The schedule said Enabled, the cron expression said cron(0 2 * * ? *), and the ECS cluster showed nothing in Tasks. Jake read the cron line twice and said, "Two in the morning where?" The schedule had been created in UTC, which is 7:30 a.m. for the shop, and the morning task was there after all, in Stopped tasks, with the reason ResourceInitializationError. Two problems, one symptom, and neither was the schedule being broken.
New to ECS or EventBridge? Our plain-English ECS guide covers clusters, tasks and services, and the EventBridge guide explains where the Scheduler sits. The commands below use the AWS CLI; on Windows Command Prompt, replace the line-ending \ with ^.
Which of the three failures do you have? Two metrics decide
A scheduled task is a chain: the scheduler fires, calls the ECS RunTask API using an execution role, ECS places the task, the task runs. Each link fails differently, and guessing costs you hours. Pull your two numbers for the last day:
# attempts and target errors for the "default" schedule group, last 24 hours, hourly buckets
for m in InvocationAttemptCount TargetErrorCount; do
echo "== $m"
aws cloudwatch get-metric-statistics --namespace AWS/Scheduler --metric-name $m \
--dimensions Name=ScheduleGroup,Value=default \
--start-time $(date -u -d '24 hours ago' +%FT%TZ) --end-time $(date -u +%FT%TZ) --period 3600 --statistics Sum \
--query "sort_by(Datapoints,&Timestamp)[].[Timestamp,Sum]" --output text
done
| InvocationAttemptCount | TargetErrorCount | Meaning | Go to |
|---|---|---|---|
| 0 | 0 | The schedule never fired | Not firing |
| > 0 | > 0 | It fired; ECS rejected the RunTask call | Role, network, DLQ |
| > 0 | 0 | It fired and ECS accepted; the task stopped, or was never placed | Stopped tasks |
Two cautions about the numbers. Metrics are delivered on a best-effort basis, so a single missing data point proves nothing; look at a whole day. And the dimension is the schedule group, not the schedule, so if several of your schedules share the default group you are reading their total. Put a troublesome schedule in its own group so you can read it alone.
Jake's two-in-the-morning question was row three: the schedule fired every day (at 7:30 a.m. local, but it fired), ECS accepted, and the task stopped. The time zone was a second, separate problem that nobody would have noticed until the report arrived at breakfast.
Zero attempts: why a schedule never fires
Check these in order; each takes you a minute.
- State.
aws scheduler get-schedule --name nightly-report --query Statemust printENABLED. A schedule you created through infrastructure code withState: DISABLEDfor testing stays that way until you flip it. - The cron expression has six fields, not five:
cron(minutes hours day-of-month month day-of-week year). A Linux five-field line pasted in is rejected at creation, but a six-field line with*in both day-of-month and day-of-week is also rejected: one of the two must be?.cron(0 2 * * ? *)is "2:00 every day." - Time zone. Without
--schedule-expression-timezone, the expression is evaluated in UTC. "It did not run at 2 a.m." often means it ran at 2 a.m. UTC while you slept. Set an IANA zone such asAsia/KolkataorAmerica/New_York; the console's preview of the next ten run times shows the result before you save. - Start and end dates. A rate-based schedule begins at
StartDate; anEndDatein the past means it will never fire again. A one-timeat(...)schedule fires once and then sits there counting toward your quota until you delete it (or setActionAfterCompletiontoDELETE). - Flexible time window. A 15-minute window on an hourly schedule means "some time in the 15 minutes after the hour," so a task you expected at 2:00 may run at 2:11 and look late to you. Set the mode to
OFFif the minute matters. Even then, precision is 60 seconds: 2:00 means between 2:00:00 and 2:00:59. - Daylight saving. In a zone that observes it, a cron time that does not exist on the spring-forward night is skipped, and on the fall-back night it runs once.
rate(1 days)is exactly 24 hours and drifts by an hour across the change. - Recent edits. A change made close to the trigger time may still fire once on the old configuration. Give your edit a few minutes before you judge it.
aws scheduler get-schedule --name nightly-report \
--query "{state: State, expr: ScheduleExpression, tz: ScheduleExpressionTimezone, window: FlexibleTimeWindow, start: StartDate, end: EndDate}"
Target errors, cause 1: the execution role
The schedule does not call ECS as you; it assumes an execution role and calls RunTask as that role. Three permissions are involved, and the console's "Create new role for this schedule" option attaches all of them. A role you built by hand often has the first and not the second, so check yours against all three:
- Trust policy: the role must trust
scheduler.amazonaws.com. A role you copied from a Lambda or EC2 setup trusts the wrong service and the assume-role step fails before ECS is ever called. ecs:RunTaskon the task definition. Grant it ontask-definition/FAMILY:*so the schedule can follow new revisions; a policy you pinned to:7breaks the day you register revision 8.iam:PassRoleon the task definition's task role and task execution role. RunTask hands those roles to the task, and the caller must be allowed to pass them. This is the one most hand-built roles miss, and the error names it:is not authorized to perform: iam:PassRole on resource. Our iam:PassRole guide has the full story.
// trust policy (who may assume the role)
{ "Version": "2012-10-17", "Statement": [ {
"Effect": "Allow", "Principal": { "Service": "scheduler.amazonaws.com" }, "Action": "sts:AssumeRole",
"Condition": { "StringEquals": { "aws:SourceAccount": "111122223333" } } } ] }
// permissions policy
{ "Version": "2012-10-17", "Statement": [
{ "Effect": "Allow", "Action": ["ecs:RunTask", "ecs:TagResource"],
"Resource": "arn:aws:ecs:ap-south-1:111122223333:task-definition/nightly-report:*",
"Condition": { "ArnLike": { "ecs:cluster": "arn:aws:ecs:ap-south-1:111122223333:cluster/shop" } } },
{ "Effect": "Allow", "Action": "iam:PassRole",
"Resource": ["arn:aws:iam::111122223333:role/nightly-report-task-role", "arn:aws:iam::111122223333:role/ecsTaskExecutionRole"],
"Condition": { "StringLike": { "iam:PassedToService": "ecs-tasks.amazonaws.com" } } },
{ "Effect": "Allow", "Action": "sqs:SendMessage", "Resource": "arn:aws:sqs:ap-south-1:111122223333:scheduler-dlq" } ] }
ecs:TagResource matters if the schedule sets tags or enables ECS managed tags; without it, a tagged RunTask is denied in full. The sqs:SendMessage line is for the dead-letter queue below. And the role must live in the same account and Region as the schedule.
"So the schedule is a person with a badge," Jake said, "and the badge has to say three things: I'm allowed in, I'm allowed to start that job, and I'm allowed to hand the job its own badge." Ethan wrote that on the role's description field.
Target errors, cause 2: Fargate without a network, or with the wrong one
A Fargate task definition uses awsvpc networking, so every RunTask call must say which subnets and security groups the task gets. A schedule with no NetworkConfiguration fails with InvalidParameterException: Network Configuration must be provided when networkMode 'awsvpc' is specified, counted in TargetErrorCount. The fix is the EcsParameters block in your target:
"EcsParameters": {
"TaskDefinitionArn": "arn:aws:ecs:ap-south-1:111122223333:task-definition/nightly-report",
"LaunchType": "FARGATE", "PlatformVersion": "LATEST", "TaskCount": 1,
"NetworkConfiguration": { "awsvpcConfiguration": {
"Subnets": ["subnet-0a1b2c3d4e5f60718"], "SecurityGroups": ["sg-0123456789abcdef0"], "AssignPublicIp": "ENABLED" } } }
The network that is present but wrong does not show up as a target error. ECS accepts the call, launches the task, and the task stops during startup because it cannot reach ECR to pull the image, Secrets Manager for its secrets, or CloudWatch Logs for its log stream. That is the ResourceInitializationError Ethan found. The rule of thumb for your subnet choice:
| Subnet | AssignPublicIp | Result |
|---|---|---|
| Public (route to an internet gateway) | ENABLED | Works |
| Public | DISABLED | No route out: ResourceInitializationError / CannotPullContainerError |
| Private with a NAT gateway | DISABLED | Works |
| Private, no NAT, no VPC endpoints | either | Fails at startup; add endpoints for ecr.api, ecr.dkr, S3, logs (and secretsmanager if used) |
Your security group needs outbound access on 443 (most default groups allow all outbound). Our ResourceInitializationError guide walks through the endpoints, and the CannotPullContainerError guide covers the image side.
Attempts, no errors, no task: read the Stopped tasks list
When the scheduler reports success and nothing is running, the task either ran and stopped, or ECS accepted the call and placed nothing. Both are visible from the ECS side, not the scheduler side, so switch consoles.
Stopped tasks. In the ECS console, open the cluster, choose Tasks, and switch the filter to Stopped. The task launched by a schedule carries the schedule in its startedBy field, and stoppedReason says why. Stopped tasks stay visible for a limited time (roughly an hour through the API), so look soon after your scheduled time, or go to CloudTrail, where every RunTask call is logged with the execution role as the caller:
# recently stopped tasks and why
aws ecs list-tasks --cluster shop --desired-status STOPPED --query taskArns --output text | tr '\t' '\n' | head -5
aws ecs describe-tasks --cluster shop --tasks TASK_ARN \
--query "tasks[].{by: startedBy, reason: stoppedReason, code: stopCode, exit: containers[].exitCode, created: createdAt}"
# did the scheduler call RunTask at all? (CloudTrail, last 24 h)
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=RunTask \
--start-time $(date -u -d '24 hours ago' +%FT%TZ) --query "Events[].[EventTime,Username]" --output text
| stoppedReason starts with | Means | Fix |
|---|---|---|
ResourceInitializationError | Could not reach ECR, Secrets Manager or CloudWatch Logs, or the log group is missing | Network; awslogs-create-group true or create the group (guide) |
CannotPullContainerError | Image name, tag or registry permission | Check the image URI and the execution role's ECR permissions |
Essential container in task exited | Your code ran and ended; a non-zero exit code is an application error | Read the exit code and the container log (guide) |
Task failed to start / OutOfMemoryError | Container killed for memory, or the runtime failed | Raise task memory; check the command |
A detail that matters for batch jobs: exit code 0 with reason "Essential container in task exited" is success. A scheduled task is supposed to finish. If you expected to see it under Running and only find it under Stopped with exit 0, your job ran.
Placed nothing. On an EC2 cluster (or a capacity provider with no instance available), RunTask can return success with the task listed in a failures array instead: reasons such as No Container Instances were found in your cluster., RESOURCE:MEMORY, RESOURCE:CPU or AGENT. The scheduler saw an HTTP 200 and counts a successful invocation; TargetErrorCount stays at zero; no task ever exists. The tells in your setup are an EC2 launch type with no instances registered (or all of them full) at the scheduled minute. Run the same call by hand and read the response:
aws ecs run-task --cluster shop --task-definition nightly-report --launch-type EC2 --count 1 --query failures
# [ { "arn": "arn:aws:ecs:...:container-instance/...", "reason": "RESOURCE:MEMORY" } ] <- placed nothing, but the call "succeeded"
Your fixes: a capacity provider with managed scaling so an instance exists when the task needs it, a smaller task size, or Fargate for a job that runs once a night and does not deserve a 24-hour instance.
The dead-letter queue: the actual error message
Metrics tell you that RunTask failed; the dead-letter queue tells you what ECS said. Create a standard SQS queue (not FIFO), give your execution role sqs:SendMessage on it, and attach it to the schedule:
aws sqs create-queue --queue-name scheduler-dlq
aws scheduler update-schedule --name nightly-report --schedule-expression "cron(0 2 * * ? *)" --schedule-expression-timezone "Asia/Kolkata" \
--flexible-time-window '{"Mode":"OFF"}' \
--target '{"Arn":"arn:aws:ecs:ap-south-1:111122223333:cluster/shop","RoleArn":"arn:aws:iam::111122223333:role/nightly-report-scheduler",
"DeadLetterConfig":{"Arn":"arn:aws:sqs:ap-south-1:111122223333:scheduler-dlq"},
"RetryPolicy":{"MaximumRetryAttempts":2,"MaximumEventAgeInSeconds":3600},
"EcsParameters":{ ...as above... }}'
# after the next failure
aws sqs receive-message --queue-url https://sqs.ap-south-1.amazonaws.com/111122223333/scheduler-dlq \
--message-attribute-names All --max-number-of-messages 1 \
--query "Messages[].MessageAttributes.{code: ERROR_CODE.StringValue, msg: ERROR_MESSAGE.StringValue, when: SCHEDULED_TIME.StringValue}"
The message attributes carry ERROR_CODE and ERROR_MESSAGE straight from the ECS API: AccessDeniedException with the missing action named, InvalidParameterException for the network block, ClusterNotFoundException for a cluster ARN in the wrong Region, ClientException: TaskDefinition not found for a deregistered pinned revision. EXHAUSTED_RETRY_CONDITION says whether retries or the maximum age ran out. If TargetErrorCount climbs and the queue stays empty, the role cannot write to the queue (or the queue's KMS key refuses the scheduler), which is itself a permissions finding you can act on.
Cron, rate and time zone, in one table
| Want | Expression | Note |
|---|---|---|
| Every day at 2:00 | cron(0 2 * * ? *) | Set the time zone or it is 2:00 UTC |
| Weekdays at 8:30 | cron(30 8 ? * MON-FRI *) | ? goes in day-of-month when day-of-week is used |
| First of the month, 00:05 | cron(5 0 1 * ? *) | Year field * = every year (1970-2199 allowed) |
| Last Friday, 10:15 | cron(15 10 ? * 6L *) | Days are 1-7 = SUN-SAT; L = last |
| Every 15 minutes | rate(15 minutes) | Starts at StartDate or immediately; nothing faster than 1 minute |
| Once, Nov 20 at 13:00 local | at(2026-11-20T13:00:00) + time zone | Delete afterwards or set ActionAfterCompletion DELETE |
Use the console's preview of the next ten run times before you save; it catches the ? rule and the time zone at once. Legacy EventBridge rules accept the same six-field cron but only in UTC, which is the next section.
The legacy version: EventBridge rules with an ECS target
Before the Scheduler existed, scheduled tasks were EventBridge rules with a schedule expression and an ECS target, and many of yours may still be running. The same three failures apply with different names:
- Role: the target uses
ecsEventsRole(or any role trustingevents.amazonaws.com) with the managed policyAmazonEC2ContainerServiceEventsRole, which grantsecs:RunTaskandiam:PassRole. A custom role needs both, exactly as above. - Metric:
FailedInvocationsin theAWS/Eventsnamespace, dimensionRuleName;TriggeredRulesconfirms the rule fired. - Time zone: rules are UTC only. A 2 a.m. local job is
cron(30 20 * * ? *)for India and shifts with daylight saving elsewhere; this alone is a reason to move your rules to the Scheduler. - Rule state must be
ENABLED; theEcsParameterson the target need the same network block for Fargate.
aws events describe-rule --name nightly-report --query "{state: State, expr: ScheduleExpression}"
aws events list-targets-by-rule --rule nightly-report --query "Targets[].{role: RoleArn, task: EcsParameters.TaskDefinitionArn, net: EcsParameters.NetworkConfiguration}"
aws cloudwatch get-metric-statistics --namespace AWS/Events --metric-name FailedInvocations --dimensions Name=RuleName,Value=nightly-report \
--start-time $(date -u -d '24 hours ago' +%FT%TZ) --end-time $(date -u +%FT%TZ) --period 3600 --statistics Sum --query "Datapoints[].Sum"
Our EventBridge rule never fires guide covers the event-pattern side of rules; scheduled rules skip the pattern and go straight to the target.
A schedule that works, end to end
aws scheduler create-schedule --name nightly-report --group-name reports \
--schedule-expression "cron(0 2 * * ? *)" --schedule-expression-timezone "Asia/Kolkata" \
--flexible-time-window '{"Mode":"OFF"}' --state ENABLED \
--target '{
"Arn": "arn:aws:ecs:ap-south-1:111122223333:cluster/shop",
"RoleArn": "arn:aws:iam::111122223333:role/nightly-report-scheduler",
"DeadLetterConfig": { "Arn": "arn:aws:sqs:ap-south-1:111122223333:scheduler-dlq" },
"RetryPolicy": { "MaximumRetryAttempts": 2, "MaximumEventAgeInSeconds": 3600 },
"EcsParameters": {
"TaskDefinitionArn": "arn:aws:ecs:ap-south-1:111122223333:task-definition/nightly-report",
"LaunchType": "FARGATE", "PlatformVersion": "LATEST", "TaskCount": 1,
"NetworkConfiguration": { "awsvpcConfiguration": {
"Subnets": ["subnet-0a1b2c3d4e5f60718", "subnet-0f1e2d3c4b5a69788"],
"SecurityGroups": ["sg-0123456789abcdef0"], "AssignPublicIp": "ENABLED" } } },
"Input": "{\"containerOverrides\":[{\"name\":\"report\",\"environment\":[{\"name\":\"REPORT_DAY\",\"value\":\"yesterday\"}]}]}"
}'
Read it against your three failures: the time zone is explicit and the window is off (not firing); the role is the one from the role section and the network block is present (target errors); the task definition ARN has no revision so new revisions are picked up; and the DLQ is wired so the next failure explains itself. Input is where container overrides go, as a JSON string in RunTask's own shape. Your test is a one-time schedule two minutes ahead (at(...)), then the Stopped tasks list with exit code 0.
Ethan's fixes were the Asia/Kolkata time zone and AssignPublicIp: ENABLED on a task that lived in a public subnet with no NAT. The Thursday night report arrived at 2:00:40 a.m. Jake asked whether the forty seconds were a problem, and Ethan explained the 60-second precision rule, and that nobody reads the report before breakfast anyway.
For IT admins: making scheduled tasks observable
- One schedule group per application, so
AWS/Schedulermetrics read per app; alarm onTargetErrorCount> 0 and onInvocationAttemptCount< expected per day. - A DLQ on every schedule, with an alarm on queue depth; it is the only place the real error message lands.
- Alarm on the task side too: an EventBridge rule on ECS Task State Change with
stopCodeother thanEssentialContainerExited, or a non-zero exit code, catches tasks that start and die. - Grant
ecs:RunTaskonFAMILY:*and point schedules at the family, so your deployments that register new revisions do not break the schedule. - Prefer the Scheduler over rules for new jobs: time zones, retries and a DLQ are built in; migrate rules when you touch them.
- A dedicated task role and task execution role per job keep the PassRole statement narrow and stable, and ECR tag immutability stops the image a schedule runs from changing under it.
Frequently asked questions
Why is my ECS scheduled task not running?
Check two CloudWatch metrics in AWS/Scheduler. InvocationAttemptCount at zero means the schedule did not fire (disabled, cron, time zone, end date). TargetErrorCount above zero means ECS rejected RunTask (execution role or Fargate network block). Attempts with no errors means the task launched and stopped, or an EC2 cluster had no room.
What permissions does the EventBridge Scheduler execution role need for ECS?
A trust policy for scheduler.amazonaws.com, ecs:RunTask on the task definition (family:* to follow revisions), iam:PassRole on the task role and task execution role with iam:PassedToService ecs-tasks.amazonaws.com, ecs:TagResource if tags are used, and sqs:SendMessage for a dead-letter queue.
Why does the schedule show success but no task appears?
Either the task started and stopped within seconds (check Stopped tasks and stoppedReason), or RunTask returned placement failures inside a successful response, which happens on EC2 clusters with no free instance. The scheduler counts that as success.
Why did my scheduled Fargate task stop with ResourceInitializationError?
The task could not reach ECR, Secrets Manager or CloudWatch Logs. A public subnet needs AssignPublicIp ENABLED; a private subnet needs a NAT gateway or VPC endpoints for ecr.api, ecr.dkr, S3 and logs. A missing log group with awslogs-create-group false causes the same error.
What is the cron format for EventBridge Scheduler?
Six fields: cron(minutes hours day-of-month month day-of-week year). One of day-of-month or day-of-week must be ?, days of the week are 1-7 or SUN-SAT, and nothing faster than one minute is allowed. cron(0 2 * * ? *) is 2:00 every day.
Does an ECS scheduled task run in my local time zone?
EventBridge Scheduler evaluates the expression in UTC unless you set a time zone such as Asia/Kolkata with --schedule-expression-timezone. Legacy EventBridge rules are UTC only.
Why did my scheduled task run 11 minutes late?
A flexible time window lets the scheduler run the task any time within the window after the scheduled minute. Set the mode to OFF for exact timing; precision is then within the scheduled minute.
Why does the error say not authorized to perform iam:PassRole?
RunTask hands the task its task role and execution role, so the scheduler's execution role must be allowed to pass both. Add an iam:PassRole statement naming those two role ARNs.
Why is InvalidParameterException "Network Configuration must be provided" in my DLQ?
The task definition uses awsvpc networking (all Fargate tasks do) and the schedule's EcsParameters has no NetworkConfiguration. Add the awsvpcConfiguration with subnets, security groups and AssignPublicIp.
Does the schedule use the latest task definition revision?
If TaskDefinitionArn has no :revision, each run uses the latest ACTIVE revision. A pinned revision keeps running the old one and fails with "TaskDefinition not found" if that revision is deregistered.
How do I see the real error when a schedule fails?
Attach a standard SQS dead-letter queue to the schedule and give the execution role sqs:SendMessage. Failed invocations arrive with ERROR_CODE and ERROR_MESSAGE straight from the ECS API.
How do I test a schedule without waiting for 2 a.m.?
Create a one-time schedule with at(...) two minutes ahead using the same target JSON, then check Stopped tasks for exit code 0. Or run aws ecs run-task by hand with the same parameters and read the failures array.
What is the difference between EventBridge Scheduler and EventBridge rules for ECS?
Rules are the older method: UTC only, role ecsEventsRole with AmazonEC2ContainerServiceEventsRole, metric FailedInvocations in AWS/Events. The Scheduler adds time zones, one-time schedules, retries, flexible windows and a DLQ, and is the recommended choice.
Why did my schedule fire twice or not at all on the daylight saving night?
In a zone that observes daylight saving, a cron time that does not exist on the spring-forward night is skipped and on the fall-back night runs once. Use UTC or a non-observing zone if a job must run every night at the same offset.
Why does a stopped task with exit code 0 appear instead of a running one?
A scheduled batch task is meant to finish. Exit code 0 under "Essential container in task exited" is a successful run; look under Stopped, not Running.
Can I pass arguments or environment variables to the scheduled task?
Yes. Put RunTask container overrides in the target's Input as a JSON string: containerOverrides with name, command or environment. The execution role does not need extra permissions for overrides.
For readers preparing for an AWS certification
We have been covering AWS certifications alongside our fixes, so here is a short extra for readers studying for one. If you only came for the fix, you already have it; feel free to skip this part.
Exams that test this topic: DevOps Engineer – Professional (DOP-C02) • CloudOps Engineer – Associate (SOA-C03) • Solutions Architect – Associate (SAA-C03).
Here are the exam-style questions this topic tends to raise, with the reasoning you need to answer them:
1. Which service is recommended for running an ECS task every night at 2 a.m. in a local time zone?
Amazon EventBridge Scheduler, which supports time zones, one-time schedules, retries and dead-letter queues.
2. A scheduled Fargate task fails with "Network Configuration must be provided". What is missing?
The awsvpc network configuration (subnets, security groups and public IP setting) in the schedule's ECS parameters.
3. Which two permissions must the scheduler's role have to start an ECS task?
ecs:RunTask on the task definition and iam:PassRole for the task role and task execution role.
4. A batch job runs once a night for ten minutes. Fargate or a dedicated EC2 instance?
Fargate, which bills only while the task runs. A 24-hour instance for a short nightly job wastes money.
5. How do you get alerted when a scheduled task starts and then fails?
An EventBridge rule on ECS Task State Change events for stopped tasks with a non-zero exit code, sending to SNS.
6. Which service fits large batch jobs with queues and job dependencies?
AWS Batch, which schedules container jobs on ECS, Fargate or EKS.
Exam codes and dates change often. Our AWS certification changes page keeps track of what is current.
The schedule now lives in its own group called reports, with an alarm on TargetErrorCount and a dead-letter queue nobody has had to read yet. Jake added one line to the runbook: "If the report is missing, look in Stopped tasks before you look at the schedule."
📌 If you keep one line from this page
InvocationAttemptCount tells you whether the schedule fired, TargetErrorCount whether ECS accepted the call, and the Stopped tasks list what happened after; fix the time zone, the execution role's RunTask and PassRole, and the Fargate network block in that order.
Six-field cron with ? · AssignPublicIp ENABLED in public subnets · EC2 placement failures count as success · DLQ for the real message.
Revision note. Written October 17, 2026. "Time and tide wait for no man," the proverb says; the scheduler waits for nobody either, but it will wait in the wrong time zone.