Back to Blog
DevOps

Cron Expressions Explained: The Complete Scheduling Reference

Master the cron syntax for scheduling recurring tasks. Covers the five-field format, special characters, common patterns, and platform differences.

By Birhrt Team

Cron: The Universal Task Scheduler

Cron is the oldest and most widely used task scheduling system in computing. Originally created for Unix in 1975 by Ken Thompson, cron expressions have become the universal standard for defining recurring schedules — used in Linux crontabs, cloud schedulers (AWS EventBridge, Google Cloud Scheduler), CI/CD pipelines (GitHub Actions, GitLab CI), and job queue libraries (BullMQ, Celery, Sidekiq).

The Five-Field Format

A standard cron expression consists of five fields separated by spaces:

┌──────── minute (0-59)
│ ┌────── hour (0-23)
│ │ ┌──── day of month (1-31)
│ │ │ ┌── month (1-12 or JAN-DEC)
│ │ │ │ ┌ day of week (0-7, 0 and 7 = Sunday, or SUN-SAT)
│ │ │ │ │
* * * * *

Example: 30 9 1-5 means "At 9:30 AM, Monday through Friday."

Special Characters

Asterisk (*): Matches every possible value.

* * * * *    → every minute of every hour of every day

Comma (,): Lists multiple values.

0 9,12,18 * * *    → at 9:00, 12:00, and 18:00 daily

Hyphen (-): Defines a range.

0 9-17 * * *    → every hour from 9:00 to 17:00

Slash (/): Defines step intervals.

*/15 * * * *    → every 15 minutes
0 */2 * * *     → every 2 hours, on the hour

20 Essential Cron Patterns

Here are the most commonly needed schedules:

Cron ExpressionDescription
*Every minute
/5 *Every 5 minutes
/15 *Every 15 minutes
0 Every hour (on the hour)
0 /6 Every 6 hours
0 0 *Daily at midnight
0 9 *Daily at 9:00 AM
30 9 1-5Weekdays at 9:30 AM
0 0 0Weekly on Sunday at midnight
0 0 1Weekly on Monday at midnight
0 0 1 First day of every month
0 0 1 1 *January 1st (yearly)
0 0 15 15th of every month
0 8-17 1-5Every hour, 8AM-5PM, weekdays
0 0 1,15 1st and 15th of every month
0 22 5Every Friday at 10 PM
0 0 6,0Weekends at midnight
/30 9-17 * 1-5Every 30 min during business hours
0 3 0Sunday at 3 AM (maintenance window)
0 0 L Last day of every month*

*Note: L (last) is not standard cron — it is a Quartz/Spring extension.

Platform Differences: Where Cron Gets Confusing

Different systems implement cron slightly differently, which is a common source of bugs:

Day of Week Numbering:

  • Standard cron (Linux): 0 = Sunday, 6 = Saturday (7 also = Sunday)
  • Quartz (Java/Spring): 1 = Sunday, 7 = Saturday
  • AWS EventBridge: 1 = Sunday, 7 = Saturday

Seconds Field:

  • Standard cron: 5 fields (no seconds)
  • Quartz: 6 fields (seconds first)
  • Spring: 6 fields (seconds first)
Linux crontab:  0 9 * * *         → 9:00 AM daily
Quartz/Spring:  0 0 9 * * ?       → 9:00 AM daily (6 fields, ? in day-of-week)
AWS EventBridge: cron(0 9 * * ? *)  → 9:00 AM daily (6 fields, year field)

The Question Mark (?): In Quartz, you must use ? in either the day-of-month or day-of-week field to indicate "no specific value." This prevents conflicts when both fields are set.

Timezone Considerations

Cron schedules execute in the timezone of the system where they run:

  • Linux crontab: Uses the system timezone (usually UTC on servers)
  • AWS EventBridge: Always UTC
  • Google Cloud Scheduler: Configurable timezone per job
  • GitHub Actions: UTC by default

Daylight Saving Time traps:

  • A 0 2 * schedule (2:00 AM) will skip one execution when clocks spring forward (2 AM does not exist) and may execute twice when clocks fall back (2 AM occurs twice).
  • Solution: Use UTC for all server-side cron jobs.

Debugging Cron Jobs

When a cron job does not fire as expected, check these common issues:

1. Path problems: Cron runs with a minimal PATH. Always use absolute paths for executables:

# ❌ May not work
0 * * * * python script.py

# ✅ Use absolute paths
0 * * * * /usr/bin/python3 /home/user/scripts/script.py

2. Environment variables: Cron does not load your shell profile (.bashrc, .zshrc). Set environment variables at the top of the crontab:

PATH=/usr/local/bin:/usr/bin:/bin
NODE_ENV=production

0 * * * * node /app/script.js

3. Output swallowing: By default, cron sends output via email. If email is not configured, output is silently lost. Redirect to a log file:

0 * * * * /app/backup.sh >> /var/log/backup.log 2>&1

4. Permission issues: The cron daemon runs as the user who owns the crontab. Ensure the script has execute permissions and the user has access to all required files.

Modern Alternatives to Cron

While cron remains essential, modern systems offer alternatives for specific use cases:

  • systemd timers: Linux systems with systemd can use timer units instead of cron. They offer better logging, dependency management, and calendar-based scheduling.
  • Cloud schedulers: AWS EventBridge, Google Cloud Scheduler, and Azure Logic Apps provide managed cron scheduling with monitoring, retry policies, and integration with cloud services.
  • Job queues: BullMQ (Node.js), Celery (Python), and Sidekiq (Ruby) support cron-like recurring jobs with built-in retry logic, concurrency control, and monitoring dashboards.

Summary

Cron expressions are a compact, standardized way to define recurring schedules. The five-field format (minute, hour, day-of-month, month, day-of-week) covers virtually every scheduling need. Watch out for platform differences in day-of-week numbering and field count, always use UTC for server-side jobs, and redirect output to log files for debugging. Despite being 50 years old, cron remains the universal scheduling language understood by every platform and every developer.

Try the Related Tool

Put this knowledge into practice with our free, privacy-first tool.

Open Cron Generator Tool →