← Blog  ·  October 2026

How to Monitor AWS Cron Jobs (Lambda, CloudWatch Events, ECS Scheduled Tasks)

Your nightly Lambda ran at midnight last Tuesday. It hasn't run since. You found out when a customer asked why their report was blank.

AWS gives you three solid ways to schedule recurring work. What it doesn't give you — by default — is any alert when that work quietly stops happening. This article covers the three main AWS scheduling patterns, why native monitoring falls short, and the simplest approach to know when a scheduled job fails or disappears.


The three AWS patterns for scheduled work

1. Lambda + EventBridge (formerly CloudWatch Events)

The most common serverless scheduling pattern. You create an EventBridge rule with a cron or rate expression, point it at a Lambda function, and AWS invokes the function on schedule.

# EventBridge cron expression — runs every day at 03:00 UTC
cron(0 3 * * ? *)

EventBridge is reliable at triggering. The silent failure happens inside the Lambda: an uncaught exception, a timeout, a downstream dependency that's unavailable. The invocation record appears in CloudWatch Logs as a success because Lambda received and ran the function — even if the business logic failed internally.

2. ECS Scheduled Tasks

For containerized workloads, you can use EventBridge to trigger an ECS task on a schedule instead of a Lambda. The container runs, does its work, and exits. ECS scheduled tasks are useful when your job needs more memory, a longer timeout, or a richer runtime environment than Lambda allows.

The monitoring challenge is the same: ECS reports the task as complete once the container exits with code 0. If your application catches its own exceptions and exits cleanly despite an internal failure, the orchestration layer sees a success.

3. EC2 cron via SSM or traditional crontab

For jobs that need to run on an EC2 instance, you either use traditional crontab directly or AWS Systems Manager (SSM) Run Command / Maintenance Windows to dispatch scheduled shell commands. SSM gives you centralized execution history, but the fundamental observability problem is identical: a job that runs and exits 0 is recorded as successful regardless of what it actually did.


Native AWS monitoring options — and why they're complex

AWS provides several mechanisms to observe Lambda and EventBridge behavior, but assembling them into reliable job-failure alerts takes real effort.

CloudWatch Alarms on Lambda metrics

You can create CloudWatch Alarms on the Errors metric for a Lambda function, which fires when the invocation throws an unhandled exception. This catches hard crashes. It does not catch: silent logic failures, jobs that time out gracefully, jobs that stop being invoked entirely (e.g. the EventBridge rule gets disabled), or Lambda functions that return success while doing nothing useful.

Lambda Destinations

Lambda Destinations let you route asynchronous invocation results to an SQS queue, SNS topic, EventBridge event bus, or another Lambda — separately for success and failure. This is useful for building pipelines but still requires you to wire up a downstream failure handler and does nothing for missed runs.

CloudWatch Logs metric filters

You can create a metric filter that scans your Lambda logs for the string ERROR or any pattern you choose, increment a counter, and alarm on that counter. This works if your code writes structured errors to stdout. It's fragile if your error messages vary, and it still doesn't catch a Lambda that simply stops being invoked.

The gap all three leave open None of these approaches alert you when a scheduled job stops running entirely. A disabled EventBridge rule, a deleted Lambda, a misconfigured IAM role — the job just disappears. CloudWatch only knows about things that happened; it has no model of things that were supposed to happen and didn't.

The dead man's switch pattern: simpler and more complete

The most reliable approach to AWS cron job monitoring doesn't involve CloudWatch Alarms at all. It inverts the problem: instead of watching for errors, you watch for the absence of success.

At the end of each successful job run, send a ping to a monitoring service. If the service doesn't receive the ping within the expected window, it fires an alert.

For a Lambda function, it's one line:

import urllib.request

def handler(event, context):
    # ... your job logic ...
    do_the_work()

    # Ping only fires if do_the_work() completes without exception
    urllib.request.urlopen(
        "https://cron.watch/ping/your-job-id",
        timeout=5
    )

Or with curl from a shell-based ECS task or EC2 cron:

# ECS task entrypoint
python /app/jobs/nightly_sync.py && \
  curl -s https://cron.watch/ping/your-job-id

The && means the ping only fires on a clean exit. A failure, timeout, or crash means the ping never arrives. The monitoring service alerts you.

This single pattern covers all three failure modes:

You don't need separate alarms for each failure mode. One missing ping catches all of them.


Putting it together for AWS

A practical setup for a Lambda + EventBridge job:

  1. Add the ping at the end of your Lambda handler — after all meaningful work completes, before returning.
  2. Set the expected interval in your monitoring service to match the EventBridge schedule, with a small grace window (e.g. for a daily job, alert if no ping in 25 hours).
  3. Test the alert path — disable the EventBridge rule and confirm you get an alert within the grace window. Then re-enable it.
  4. Optionally keep a CloudWatch Alarm on Lambda Errors as a secondary signal for hard crashes that happen before your ping line.

For ECS Scheduled Tasks, the same approach applies: the ping goes at the end of the container's main process. For EC2 cron via SSM, it goes at the end of the shell command.

📟 Monitor your AWS cron jobs with one line

CronWatch uses exactly this pattern. Add one curl line to your Lambda, ECS task, or EC2 cron job and get alerted by email or Slack if it stops running. No CloudWatch Alarms to configure. No metric filters to maintain. $9/month early access.

Join CronWatch early access → Parse a cron expression

← All articles  ·  CronWatch  ·  Cron parser tool