Back to Blog
Infrastructure12 min read

AWS Lambda Scheduled Events vs Cron Jobs: When to Use Each

AWS Lambda with EventBridge can run code on a schedule without managing servers. But is it actually the right choice for your scheduled tasks? This guide breaks down the real trade-offs between Lambda schedules, traditional crontab, and external cron services so you can pick the right tool for each job.

How AWS Lambda Scheduled Events Work

AWS does not have a standalone "cron service." Instead, you combine two services: Amazon EventBridge (formerly CloudWatch Events) creates a rule that fires on a schedule, and AWS Lambda executes your code when the rule triggers. EventBridge acts as the scheduler; Lambda acts as the worker.

The setup flow looks like this: you create an EventBridge rule with a schedule expression, point it at a Lambda function as the target, and deploy. AWS handles the rest. No EC2 instances, no crontab files, no daemon to keep alive.

There are two types of schedule expressions in EventBridge, and understanding the difference matters.

rate() vs cron() Expressions in EventBridge

EventBridge supports two scheduling syntaxes. They look similar but behave differently.

The rate() Expression

The simpler option. It defines a fixed interval between invocations:

rate(5 minutes)    # Every 5 minutes
rate(1 hour)       # Every hour
rate(7 days)       # Every 7 days

The first execution starts relative to when you create or update the rule, not at any specific clock time. If you create a rate(1 hour) rule at 2:37 PM, it fires at 3:37, 4:37, 5:37, and so on. There is no way to anchor it to a specific minute.

The cron() Expression

For precise scheduling. AWS uses a six-field cron format, which differs from the standard five-field Unix format:

# AWS EventBridge cron (6 fields):
cron(minute hour day-of-month month day-of-week year)

# Standard Unix cron (5 fields):
minute hour day-of-month month day-of-week

# Examples:
cron(0 9 * * ? *)          # 9:00 AM UTC daily
cron(0 18 ? * MON-FRI *)   # 6:00 PM UTC weekdays
cron(0 0 1 * ? *)          # Midnight on the 1st of each month
DifferenceUnix cronAWS EventBridge cron()
Fields56 (adds year)
Day-of-week0-6 (Sun=0)1-7 (Sun=1) or SUN-SAT
? wildcardNot supportedRequired in day-of-month or day-of-week
TimezoneSystem timezoneUTC only (EventBridge Scheduler supports TZ)

The ? wildcard is a common source of errors. You must use it in either the day-of-month or day-of-week field (but not both). It means "no specific value" and tells EventBridge to ignore that field. If you use * in both, the rule will fail to save.

If you find AWS cron syntax confusing, you are not alone. Our cron expression generator outputs standard 5-field expressions that work with CronJobPro, traditional crontab, and most other scheduling tools.

Lambda Timeout and Execution Limits

Lambda functions have a hard limit of 15 minutes per invocation. If your scheduled task takes longer than that, Lambda will kill the process mid-execution. There is no way to extend this limit.

Other limits worth knowing:

LimitValueImpact on Scheduled Tasks
Max execution time900 secondsLong-running jobs must be split into chunks
Memory128 MB – 10 GBMemory-intensive tasks get expensive fast
Deployment size50 MB zippedLarge dependencies may not fit
/tmp storage512 MB – 10 GBTemp files are wiped between invocations
Concurrent executions1,000 defaultScheduled jobs compete with API handlers

That concurrency limit is particularly important. If you run 50 API-triggered Lambda functions and 10 scheduled Lambda functions in the same account, they share the same pool. A burst of API traffic can throttle your scheduled jobs or vice versa.

Cold Starts: The Hidden Latency

When Lambda has not run a function recently, it needs to provision a new execution environment. This is called a cold start, and it adds latency before your code actually begins running.

Cold start times depend on runtime, deployment size, and whether you are inside a VPC:

RuntimeTypical Cold StartIn VPC
Python100–300 ms+200–500 ms
Node.js100–300 ms+200–500 ms
Java / .NET500 ms – 5 s+200–500 ms
Docker image1–10 s+200–500 ms

For scheduled tasks that run hourly or less frequently, cold starts are virtually guaranteed because Lambda recycles idle environments after roughly 5-15 minutes of inactivity. A function scheduled to run once per day will cold-start every single time.

You can mitigate this with Provisioned Concurrency, which keeps warm environments ready. But it costs $0.0000041667 per GB-second of provisioned concurrency, which means you are paying 24/7 even when the function only runs once a day. At that point, you are losing the cost advantage of serverless.

Pricing: What Lambda Scheduled Jobs Actually Cost

Lambda pricing has three components for scheduled tasks: request charges, compute charges, and EventBridge charges (free for schedule rules).

# Lambda pricing (us-east-1, March 2026):
Requests:      $0.20 per 1M invocations
Compute:       $0.0000166667 per GB-second
Free tier:     1M requests + 400,000 GB-seconds / month

# Example: Run a 256 MB function for 10 seconds, every 15 minutes
Invocations:   4 × 24 × 30 = 2,880 / month
Compute:       2,880 × 10s × 0.25 GB = 7,200 GB-seconds
Cost:          ~$0.12 / month (within free tier for first year)

# Example: 20 scheduled functions, 512 MB, 30s each, every 5 minutes
Invocations:   20 × 12 × 24 × 30 = 172,800 / month
Compute:       172,800 × 30s × 0.5 GB = 2,592,000 GB-seconds
Cost:          ~$43.20 / month (no free tier left)

For a handful of lightweight jobs, Lambda is effectively free. But costs scale surprisingly fast when you add more functions, increase memory, or extend execution times. And this does not include CloudWatch Logs costs (typically $0.50/GB ingested), which can exceed the Lambda compute cost if your functions produce verbose output.

For comparison: CronJobPro's Pro plan at €3.99/month includes 50 scheduled jobs with monitoring, retries, and notifications built in. No Lambda configuration, no IAM policies, no CloudWatch costs. For HTTP-based scheduled tasks, it is significantly simpler and often cheaper than the Lambda approach. See pricing.

Error Handling and Retry Behavior

When EventBridge triggers a Lambda function and the invocation fails, the retry behavior depends on the invocation type. EventBridge uses asynchronous invocation, which means:

  • Lambda retries the function twice on failure (configurable to 0, 1, or 2 retries).
  • There is a delay between retries (typically 1 minute for the first retry, then longer). The exact timing is not guaranteed.
  • After all retries are exhausted, the event is discarded unless you have configured a dead-letter queue (SQS or SNS).
  • If the function succeeds but returns an error in the response body, Lambda does not retry. You need to throw an exception or return a non-200 status for retries to kick in.

Setting up proper error handling requires configuring Lambda destination on failure, CloudWatch alarms for error metrics, and potentially an SNS topic for notifications. Each of these is a separate AWS service with its own configuration.

Monitoring with CloudWatch

Every Lambda invocation automatically sends logs to CloudWatch Logs and metrics to CloudWatch Metrics. The key metrics for scheduled tasks are:

# Useful CloudWatch metrics for scheduled Lambda:
Invocations        # Total number of times the function ran
Errors             # Invocations that resulted in a function error
Throttles          # Invocations that were throttled (concurrency limit)
Duration           # How long the function ran (ms)
ConcurrentExec     # Number of simultaneous executions

# CloudWatch alarm example (Terraform):
resource "aws_cloudwatch_metric_alarm" "lambda_errors" {
  alarm_name          = "scheduled-job-errors"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "Errors"
  namespace           = "AWS/Lambda"
  period              = 300
  statistic           = "Sum"
  threshold           = 0
  alarm_actions       = [aws_sns_topic.alerts.arn]
  dimensions = {
    FunctionName = aws_lambda_function.scheduled_job.function_name
  }
}

Setting this up properly means creating CloudWatch alarms, SNS topics, and subscription endpoints for each function. It works, but the configuration overhead is significant compared to a service that includes monitoring by default.

When Lambda Wins

Lambda scheduled events are the right choice in specific situations:

  • You are already deep in AWS. If your entire stack is on AWS and your team knows CloudFormation or CDK, adding an EventBridge rule is just a few lines of infrastructure code.
  • The task needs AWS SDK access. If your scheduled job processes S3 objects, queries DynamoDB, or publishes to SQS, Lambda is the natural fit because the IAM role grants direct access.
  • The task is compute-heavy. Data transformation, image processing, or ML inference that needs CPU and memory rather than just an HTTP call.
  • You need sub-minute frequency. With Step Functions or custom polling, Lambda can execute at intervals shorter than one minute, though this gets complex.

When Traditional Cron or an External Service Wins

Lambda is not the best choice for every scheduled task. An external cron service like CronJobPro, or even a plain crontab, is often more practical:

  • Your task is an HTTP endpoint. If the work is already exposed as a web endpoint (an API route, a webhook handler, a health check), wrapping it in a Lambda function adds unnecessary complexity. Just schedule the HTTP call directly.
  • You want monitoring without building it. Lambda plus CloudWatch plus SNS requires gluing three services together. A purpose-built cron service includes execution history, failure alerts, and dashboards out of the box.
  • Your team is not on AWS. If you host on Vercel, Railway, DigitalOcean, or your own servers, adding an AWS account just for scheduled tasks introduces operational overhead and vendor coupling.
  • Tasks run longer than 15 minutes. Database migrations, large file processing, or batch operations that need 30+ minutes cannot run in Lambda at all.
  • You want timezone support. Standard EventBridge rules run in UTC only. EventBridge Scheduler (a newer service) supports timezones but adds more configuration.

Step-by-Step: Setting Up a Lambda Scheduled Event

If you decide Lambda is the right tool, here is how to set it up. This example uses the AWS CLI, but the same configuration applies in CloudFormation, CDK, or Terraform.

# 1. Create the Lambda function
aws lambda create-function \
  --function-name daily-cleanup \
  --runtime python3.12 \
  --handler lambda_function.lambda_handler \
  --role arn:aws:iam::123456789:role/lambda-exec-role \
  --zip-file fileb://function.zip \
  --timeout 300 \
  --memory-size 256

# 2. Create the EventBridge rule with a cron schedule
aws events put-rule \
  --name daily-cleanup-schedule \
  --schedule-expression "cron(0 3 * * ? *)" \
  --description "Run daily cleanup at 3 AM UTC"

# 3. Grant EventBridge permission to invoke the function
aws lambda add-permission \
  --function-name daily-cleanup \
  --statement-id eventbridge-invoke \
  --action lambda:InvokeFunction \
  --principal events.amazonaws.com \
  --source-arn arn:aws:events:us-east-1:123456789:rule/daily-cleanup-schedule

# 4. Add the Lambda function as the rule target
aws events put-targets \
  --rule daily-cleanup-schedule \
  --targets "Id"="1","Arn"="arn:aws:lambda:us-east-1:123456789:function:daily-cleanup"

That is four CLI commands with ARNs, IAM permissions, and target configurations. Compare this to scheduling the same task with an external cron service: enter a URL, pick a schedule, and save.

Side-by-Side Comparison

FactorLambda + EventBridgeExternal Cron Service
Setup time15–60 min (IAM, function, rule, permissions)2 minutes
MonitoringBuild it yourself (CloudWatch + SNS)Built-in dashboard + alerts
Max duration15 minDepends on your endpoint (no limit)
TimezoneUTC (Scheduler supports TZ)Any timezone per job
Cost (10 daily jobs)~$0 (free tier) to ~$5/mo€3.99/mo (CronJobPro Pro)
Best forCompute tasks inside AWSHTTP-based scheduled tasks

The Bottom Line

AWS Lambda scheduled events are a solid option when your tasks need direct access to AWS resources and your team is comfortable with the configuration overhead. For everything else, particularly HTTP-based scheduled tasks, an external cron service removes the operational complexity while adding monitoring, retries, and notifications that would take hours to replicate in AWS.

If your scheduled tasks boil down to "call this URL every X minutes," you do not need Lambda. You need a scheduler with built-in reliability. And if you are already using cron expressions, you can browse common patterns or build custom expressions to get started in seconds.

Related Articles

Skip the Lambda boilerplate

Schedule HTTP requests with monitoring, retries, and Slack/email notifications. No AWS configuration required. Free for up to 5 jobs.