Cron Expression Guide
A comprehensive reference for understanding and writing cron expressions, from basic syntax to advanced scheduling patterns across different platforms.
What Is Cron?
Cron is a time-based job scheduler found on Unix and Unix-like operating systems, including Linux and macOS. The name comes from the Greek word "chronos," meaning time. First introduced in Version 7 Unix in 1979, cron has become the de facto standard for scheduling recurring tasks on servers and workstations.
A cron daemon runs continuously in the background, checking a schedule table called a crontab (cron table) once per minute. When the current date and time match the pattern defined in a crontab entry, the associated command is executed. This makes cron essential for system administration, DevOps automation, and application maintenance tasks like log rotation, backups, report generation, and data synchronization.
Today, the cron expression format extends far beyond Unix systems. It is used by cloud schedulers (AWS EventBridge, Google Cloud Scheduler, Azure Functions), container orchestrators (Kubernetes CronJobs), CI/CD platforms (GitHub Actions, GitLab CI), and task queue libraries (Celery, Bull, node-cron) to define recurring schedules in a compact, human-readable syntax.
The 5-Field Cron Syntax
A standard cron expression consists of five fields separated by spaces. Each field represents a different unit of time, and together they define precisely when a task should execute. The fields, in order, are:
| Field | Allowed Values | Description |
|---|---|---|
| Minute | 0–59 | The minute of the hour when the job runs |
| Hour | 0–23 | The hour of the day (24-hour format) |
| Day of Month | 1–31 | The calendar day of the month |
| Month | 1–12 | The month of the year (1 = January) |
| Day of Week | 0–6 | The day of the week (0 = Sunday) |
For example, the expression 30 9 * * 1-5 means "at 9:30 AM, Monday through Friday." The minute field is 30, the hour is 9, day of month and month are wildcards (any value), and day of week is 1–5 (Monday to Friday).
Some extended cron implementations add a sixth field for seconds (0–59) at the beginning, or allow year as a seventh field. However, the standard 5-field format remains the most widely used and universally supported version. CronGen focuses on this standard format for maximum compatibility.
Special Characters
Cron expressions support four special characters that enable flexible scheduling patterns beyond simple fixed values:
Wildcard (Asterisk)
Matches every possible value for a field. An asterisk in the hour field means "every hour." When all five fields are asterisks (* * * * *), the job runs every single minute.
List (Comma)
Specifies a list of discrete values. For example, 1,15 in the day-of-month field runs the job on the 1st and 15th. You can combine as many values as needed: 0,15,30,45 in the minute field runs at four specific minutes each hour.
Range (Hyphen)
Defines an inclusive range of values. The expression 1-5 in the day-of-week field matches Monday through Friday. Ranges can be combined with other operators: 9-17 in the hour field restricts execution to business hours.
Step (Slash)
Specifies an interval or step value. The notation */10 means "every 10th value starting from 0." In the minute field, */15 triggers at 0, 15, 30, and 45 minutes past each hour. You can also combine with ranges: 1-30/5 fires at minutes 1, 6, 11, 16, 21, and 26.
Common Cron Patterns
Below are frequently used cron schedules that cover the most common automation scenarios. Each expression is linked to a detailed example page with syntax breakdowns and use cases.
| Expression | Schedule | Runs Per Day |
|---|---|---|
| * * * * * | Every minute | 1,440 |
| */5 * * * * | Every 5 minutes | 288 |
| */15 * * * * | Every 15 minutes | 96 |
| 0 * * * * | Every hour | 24 |
| 0 */6 * * * | Every 6 hours | 4 |
| 0 0 * * * | Daily at midnight | 1 |
| 0 9 * * 1-5 | Weekdays at 9 AM | 1 (weekdays) |
| 0 0 * * 0 | Weekly (Sundays) | 1/week |
| 0 0 1 * * | Monthly (1st) | 1/month |
| 0 0 1 1 * | Yearly (Jan 1st) | 1/year |
For a full list with detailed explanations, visit the examples page.
Cron Across Platforms
While the core cron syntax is consistent, different platforms have their own ways of defining and managing cron schedules. Here is how cron is used across popular environments:
Linux / macOS (crontab)
The traditional way to manage cron jobs on Unix systems. Use crontab -e to edit your personal cron schedule, or crontab -l to list existing entries. System-wide cron jobs go in /etc/crontab or the /etc/cron.d/ directory. Each line follows the format: minute hour dom month dow command.
Docker
Containers often need periodic tasks for health checks, log cleanup, or data processing. You can install cron inside a container and add entries via a crontab file during the Docker build. Alternatively, use a lightweight scheduler like supercronic which is designed specifically for containers and handles signal forwarding and log output correctly.
Kubernetes CronJobs
Kubernetes provides a native CronJob resource that creates Job objects on a recurring schedule. The schedule field uses standard cron syntax. CronJobs support concurrency policies, job history limits, and deadline seconds to control behavior when jobs overlap or fail. This is the preferred way to run periodic workloads in Kubernetes clusters.
CI/CD Pipelines
GitHub Actions uses cron expressions in its schedule trigger to run workflows at fixed intervals. GitLab CI supports pipeline schedules through its web interface using the same cron format. These are commonly used for nightly builds, dependency update checks, security scans, and automated testing.
Cloud Schedulers
Major cloud providers offer managed cron services: AWS EventBridge Scheduler (formerly CloudWatch Events) uses cron and rate expressions to trigger Lambda functions, Step Functions, and other AWS services. Google Cloud Scheduler sends HTTP requests, Pub/Sub messages, or App Engine requests on a cron schedule. Azure Functions supports timer triggers with cron expressions in the function.json configuration.
Timezone Considerations
By default, cron schedules execute based on the system's local timezone. On a server set to UTC, 0 9 * * * runs at 9:00 AM UTC. If your application serves users in different timezones, this distinction matters significantly.
On Linux, you can set the TZ environment variable in your crontab to override the timezone for specific jobs. Kubernetes CronJobs added timezone support (via the timeZone field) starting in version 1.27. Cloud schedulers like Google Cloud Scheduler and AWS EventBridge also support explicit timezone configuration.
Be aware of daylight saving time (DST) transitions. When clocks spring forward, a job scheduled during the skipped hour will not run. When clocks fall back, a job scheduled during the repeated hour may run twice. For critical tasks, consider scheduling at times that are not affected by DST transitions (like 3:00 AM or later), or use UTC to avoid the issue entirely.
Common Mistakes and Troubleshooting
Even experienced developers make cron configuration errors. Here are the most frequent pitfalls and how to avoid them:
Confusing Day of Month and Day of Week
When both day-of-month and day-of-week are set to non-wildcard values, most cron implementations run the job when either condition is met (OR logic), not when both are met (AND logic). This often causes unexpected extra executions. If you want to restrict by both, consider using a wrapper script that checks the date.
Forgetting environment variables
Cron runs commands with a minimal environment. Your PATH, HOME, and other variables may differ from your interactive shell. Always use absolute paths for commands and explicitly set needed environment variables in your crontab or script.
Missing output redirection
By default, cron emails command output to the crontab owner. If email is not configured (common on modern servers), the output is silently discarded. Redirect stdout and stderr to log files to capture output for debugging: command >> /var/log/myjob.log 2>&1.
Overlapping executions
If a job takes longer than the interval between runs, multiple instances can overlap. Use a lock file (flock), a PID file, or a task queue to prevent concurrent executions of the same job.
Wrong field order
The order is always minute, hour, day-of-month, month, day-of-week. A common mistake is swapping hour and minute, which can result in a job running at completely wrong times. Use a visual tool like CronGen to verify your expression before deploying.
Best Practices
- 1
Use descriptive comments above each crontab entry to explain what the job does and why it runs at that time.
- 2
Always test your cron expressions with a visual tool before deploying to production. Verify the next several run times to ensure the schedule matches your intent.
- 3
Log all cron job output to files with timestamps. Include both stdout and stderr for complete visibility.
- 4
Set up monitoring and alerting for critical cron jobs. A missed backup or failed data sync can go unnoticed for days without proper alerts.
- 5
Use version control for your crontab configurations. Store them alongside your application code so changes are tracked and reviewable.
- 6
Stagger job start times across your fleet to avoid thundering herd problems. Instead of scheduling all servers at minute 0, spread them across different minutes.
- 7
Consider using a centralized job scheduler for complex workflows with dependencies, retries, and failure handling instead of standalone cron entries.