blog.dopana

Back

Need to automate periodic tasks like backups, email sending, or data processing? AWS Lambda combined with CloudWatch Events/EventBridge is the perfect serverless solution to replace traditional cron jobs. This guide focuses on TypeScript/Node.js implementations for production-ready scheduled jobs.

Overview of Lambda Scheduled Jobs#

AWS Lambda is a serverless compute service that allows you to run code without managing servers. When combined with scheduling services, you can:

  • Automate tasks: Backups, report generation, data cleanup
  • Save costs: Pay only when code executes
  • Auto-scale: Handle increased load without configuration
  • High availability: AWS ensures availability

[!NOTE] AWS currently recommends using EventBridge Scheduler instead of legacy CloudWatch Events for new scheduled jobs.

flowchart LR
    subgraph Scheduler["Trigger Services"]
        direction TB
        EBS["EventBridge Scheduler<br/>(Timezone / Retry / Flexible window)"]
        CWE["CloudWatch Events<br/>(Legacy Cron)"]
    end

    subgraph Serverless["Serverless Compute"]
        Lambda["AWS Lambda Function<br/>(Node.js / TypeScript)"]
        DLQ["Dead Letter Queue (SQS)<br/>(Failed invocations storage)"]
    end

    subgraph Targets["Target Tasks & Monitoring"]
        DB[(Database / S3 Bucket)]
        Log["CloudWatch Logs / Alarms"]
    end

    EBS -->|Scheduled Invoke| Lambda
    CWE -.->|Basic Invoke| Lambda
    Lambda -.->|Failures / Retry Exceeded| DLQ
    Lambda -->|Read / Write Data| DB
    Lambda -->|Emit Logs & Metrics| Log

EventBridge Scheduler is the modern scheduling service with enhanced features compared to CloudWatch Events.

Advantages of EventBridge Scheduler#

  • Timezone support: Not limited to UTC only
  • Flexible time windows: Run within flexible time ranges
  • Built-in retry: Automatic retry on failure
  • One-time schedules: Support for single execution
  • Dead Letter Queue: Better failure handling

Step 1: Create TypeScript Lambda Function#

Step 2: Create IAM Role#

Lambda needs permissions to execute the job and write logs:

trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
json

Policy permissions:

Step 3: Create Schedule with EventBridge Scheduler#

Using AWS Console#

  1. Go to EventBridge Scheduler console
  2. Click Create schedule
  3. Select Recurring schedule
  4. Configure schedule expression:
# Run daily at 9:00 AM UTC
cron(0 9 * * ? *)

# Run every 15 minutes
rate(15 minutes)

# Run weekly on Monday 9:00 AM
cron(0 9 ? * MON *)

# Run on first day of each month
cron(0 0 1 * ? *)
bash
  1. Select Lambda function as target
  2. Configure timezone (if needed):
# 9:00 AM Eastern Time
cron(0 9 ? * MON *)
timezone: America/New_York
bash
  1. Configure flexible time window (optional):
# Run within 15 minutes after scheduled time
mode: FLEXIBLE
maximum_window_in_minutes: 15
bash
  1. Setup retry policy:
maximum_retry_attempts: 3
maximum_event_age_in_seconds: 3600
bash

Using AWS CLI#

aws scheduler create-schedule \
  --name daily-job \
  --schedule-expression 'cron(0 9 * * ? *)' \
  --schedule-expression-timezone 'UTC' \
  --target '{
    "Arn": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
    "RoleArn": "arn:aws:iam::123456789012:role/scheduler-role"
  }' \
  --flexible-time-window '{
    "Mode": "FLEXIBLE",
    "MaximumWindowInMinutes": 15
  }'
bash

Using Terraform#

Method 2: CloudWatch Events (Legacy)#

CloudWatch Events is the traditional method, still supported but with fewer features.

Step 1: Create Lambda Function#

Same as Scheduler method.

Step 2: Create CloudWatch Rule#

Using AWS Console#

  1. Go to CloudWatch console
  2. Select Events → Rules
  3. Click Create rule
  4. Select Schedule expression
  5. Enter cron expression:
# 9:00 AM UTC daily
0 9 * * ? *

# Every 5 minutes
rate(5 minutes)
bash
  1. Select Lambda function as target
  2. Configure permission (AWS will auto-create)

Using AWS CLI#

Cron Expression Guide#

EventBridge uses 6-field cron expression:

cron(Minutes Hours Day-of-month Month Day-of-week Year)
text

Example Cron Expressions#

Field Values#

FieldValuesSpecial Characters
Minutes0-59, - * /
Hours0-23, - * /
Day of month1-31, L, W, - * / ? L W
Month1-12, JAN-DEC, - * /
Day of week1-7, SUN-SAT, ?, L, #, - * / ? L #
Year1970-2199, - * /

[!WARNING] Use ? when day-of-month or day-of-week is constrained, don’t use both fields simultaneously.

Best Practices#

1. Idempotency#

Ensure your handler is idempotent for safe retries:

2. Dead Letter Queue (DLQ)#

Setup DLQ to handle failed invocations:

3. Overlap Prevention#

Prevent overlapping executions with DynamoDB lock:

4. Monitoring and Logging#

Use CloudWatch Logs and Metrics:

5. Error Handling#

Handle errors gracefully:

Comparison: EventBridge Scheduler vs CloudWatch Events#

FeatureEventBridge SchedulerCloudWatch Events
Schedule typescron + rate + one-timecron + rate
Timezone support✅ Any timezone❌ UTC only
Flexible windows✅ Yes❌ No
Built-in retry✅ Yes❌ No (need DLQ)
Cost$1.00/M invocationsFree (first 5M/month)
Use caseProduction jobsSimple recurring jobs

Practical Example: Daily Database Cleanup#

Schedule with EventBridge Scheduler:

# Run daily at 2:00 AM UTC
cron(0 2 * * ? *)
bash

Troubleshooting#

Job not running#

  1. Check schedule expression: Ensure cron syntax is correct
  2. Verify IAM permissions: Lambda has necessary permissions
  3. Check CloudWatch Logs: Look for error messages
  4. Verify target ARN: Ensure Lambda function ARN is correct

Job runs but fails#

  1. Review CloudWatch Logs: Find error messages
  2. Check timeout: Lambda might be timing out
  3. Verify resource permissions: Database, S3, etc. access
  4. Test locally: Run Lambda locally to debug

Overlapping executions#

  1. Implement lock mechanism: Use DynamoDB or Redis
  2. Use reserved concurrency: Limit concurrent executions
  3. Add idempotency: Ensure handler is idempotent

Cleanup Resources#

When no longer needed, clean up resources:

# Delete schedule
aws scheduler delete-schedule --name daily-job

# Delete CloudWatch rule
aws events delete-rule --name daily-lambda-rule

# Delete Lambda function
aws lambda delete-function --function-name my-function

# Delete IAM role
aws iam delete-role --role-name scheduler-role
bash

Conclusion#

AWS Lambda combined with EventBridge Scheduler/CloudWatch Events provides a powerful solution for scheduled jobs:

  • EventBridge Scheduler: For production jobs with timezone support, retry, flexible windows
  • CloudWatch Events: For simple recurring jobs with cost efficiency

Key takeaways:

  1. Use EventBridge Scheduler for production
  2. Implement idempotency and error handling
  3. Setup monitoring with CloudWatch
  4. Use DLQ for failed invocations
  5. Prevent overlapping executions

References#