intermediate 14 min read

How to Set Up Cron Jobs with AWS Lambda & EventBridge

Learn how to schedule AWS Lambda functions using EventBridge (CloudWatch Events) cron expressions. Covers console, CLI, CDK, SAM, and monitoring.

Prerequisites

  • AWS account
  • AWS CLI configured
  • Basic Lambda knowledge

How AWS Cron Scheduling Works

AWS uses Amazon EventBridge (formerly CloudWatch Events) to trigger Lambda functions on a schedule. You create a rule with a cron expression, and EventBridge invokes your Lambda function at the specified times.

AWS cron expressions use a 6-field format that includes a year field and requires the ? character for either day-of-month or day-of-week.

Quick Start: AWS Console

Step 1: Create a Lambda function in the AWS Console

Step 2: Add an EventBridge trigger:

  • Go to your Lambda function → Add trigger → EventBridge
  • Select "Create a new rule"
  • Rule type: Schedule expression
  • Expression: cron(0 9 ? * MON-FRI *) (weekdays at 9 AM UTC)

Step 3: Save and test

You can also test immediately using the "Test" button in the Lambda console.

AWS CLI Setup

bash
# Create the Lambda function
aws lambda create-function \
  --function-name my-scheduled-task \
  --runtime nodejs20.x \
  --handler index.handler \
  --zip-file fileb://function.zip \
  --role arn:aws:iam::123456789:role/lambda-role

# Create the EventBridge rule
aws events put-rule \
  --name my-schedule \
  --schedule-expression "cron(0 9 ? * MON-FRI *)"

# Add Lambda as the target
aws events put-targets \
  --rule my-schedule \
  --targets "Id"="1","Arn"="arn:aws:lambda:us-east-1:123456789:function:my-scheduled-task"

# Grant EventBridge permission to invoke Lambda
aws lambda add-permission \
  --function-name my-scheduled-task \
  --statement-id my-schedule-permission \
  --action lambda:InvokeFunction \
  --principal events.amazonaws.com \
  --source-arn arn:aws:events:us-east-1:123456789:rule/my-schedule

AWS CDK Setup

typescript
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as events from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';

const fn = new lambda.Function(this, 'ScheduledFunction', {
  runtime: lambda.Runtime.NODEJS_20_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('lambda'),
  timeout: cdk.Duration.minutes(5),
});

new events.Rule(this, 'ScheduleRule', {
  schedule: events.Schedule.cron({
    minute: '0',
    hour: '9',
    weekDay: 'MON-FRI',
  }),
  targets: [new targets.LambdaFunction(fn)],
});

AWS Cron Expression Syntax

AWS uses a 6-field cron format:

cron(minute hour day-of-month month day-of-week year)

Key differences from standard cron:

  • 6 fields (includes year)
  • ? (question mark) is required for either day-of-month or day-of-week (you can't specify both)
  • L — last day (e.g., L in day-of-month = last day of month)
  • W — nearest weekday (e.g., 15W = nearest weekday to the 15th)
  • # — nth day (e.g., FRI#2 = second Friday)

Examples:

  • cron(0 9 ? * MON-FRI *) — Weekdays at 9 AM UTC
  • cron(*/5 * ? * * *) — Every 5 minutes
  • cron(0 0 1 * ? *) — First day of every month
  • cron(0 12 ? * 2#1 *) — First Monday at noon

Common AWS Cron Expressions

  • cron(*/5 * ? * * *) — Every 5 minutes
  • cron(0 * ? * * *) — Every hour
  • cron(0 0 ? * * *) — Daily at midnight UTC
  • cron(0 9 ? * MON-FRI *) — Weekdays at 9 AM UTC
  • cron(0 0 1 * ? *) — First day of every month
  • cron(0 0 ? * SUN *) — Every Sunday at midnight
  • cron(0 0 L * ? *) — Last day of every month

You can also use rate expressions for simple intervals:

  • rate(5 minutes)
  • rate(1 hour)
  • rate(1 day)

Every weekday at 9:00 AM

Next runs (UTC):

Mon, May 18, 2026 09:00

Tue, May 19, 2026 09:00

Wed, May 20, 2026 09:00

Monitoring with CloudWatch

Lambda metrics to watch:

  • Invocations — confirms your schedule is triggering
  • Errors — failed invocations
  • Duration — execution time (watch for approaching timeout)
  • Throttles — concurrency limit hit

Set up an alarm:

bash
aws cloudwatch put-metric-alarm \
  --alarm-name "ScheduledTaskErrors" \
  --metric-name Errors \
  --namespace AWS/Lambda \
  --dimensions Name=FunctionName,Value=my-scheduled-task \
  --statistic Sum \
  --period 300 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1 \
  --alarm-actions arn:aws:sns:us-east-1:123456789:my-alerts

Production Tips

Timeout: Set your Lambda timeout higher than the expected execution time. The default is 3 seconds — increase it for cron jobs.

Dead letter queue: Configure a DLQ for failed invocations so you don't lose events:

typescript
// CDK
fn.addEventSource(new targets.LambdaFunction(fn, {
  deadLetterQueue: new sqs.Queue(this, 'DLQ'),
  retryAttempts: 2,
}));

Cost: EventBridge rules are free. You only pay for Lambda invocations. A function running every 5 minutes with 128MB and 1-second duration costs roughly $0.10/month.

Cold starts: Scheduled Lambda functions may experience cold starts if they run infrequently. Use Provisioned Concurrency for latency-sensitive tasks.

Frequently Asked Questions