What Is a Cron Expression?
A cron expression is a compact string that defines a recurring schedule. Originally built into Unix and Linux systems in the 1970s, cron has become the universal language for scheduling automated tasks across virtually every platform in modern computing. Whether you are rotating log files on a bare-metal server, triggering a Kubernetes CronJob, scheduling a GitHub Actions workflow, or setting up an AWS EventBridge rule, you are writing (or reading) cron expressions.
The standard cron expression uses five fields separated by spaces. Each field represents a unit of time, and together they answer the question: "When should this task run?" The five fields, from left to right, are:
| Field | Allowed Values | Description |
|---|---|---|
| Minute | 0 – 59 | The minute of the hour when the job fires |
| Hour | 0 – 23 | The hour of the day (24-hour clock) |
| Day of Month | 1 – 31 | The calendar day |
| Month | 1 – 12 | The month of the year |
| Day of Week | 0 – 6 | Sunday (0) through Saturday (6) |
A simple example: 0 9 * * 1-5 means "at minute 0, hour 9, any day of the month, any month, Monday through Friday" — in plain English, every weekday at 9:00 AM. The asterisks are wildcards meaning "every possible value" for that field.
Cron Expression Syntax
Beyond simple numbers and wildcards, cron supports four special characters that give you precise control over scheduling:
Asterisk (*) — Any Value
The wildcard. Placing * in a field means "every" value within the allowed range. * * * * * fires every single minute of every hour of every day — the most frequent schedule possible with standard cron.
Comma (,) — List
Specifies multiple discrete values. 0 9,17 * * * fires at 9:00 AM and 5:00 PM every day. You can list as many values as you need: 1,15,28 * * * * fires on minutes 1, 15, and 28 of every hour.
Hyphen (-) — Range
Defines a continuous range. 0 9 * * 1-5 means Monday through Friday. Ranges are inclusive on both ends, so 1-5 includes 1, 2, 3, 4, and 5.
Slash (/) — Step
Defines intervals. */5 * * * * means every 5 minutes (0, 5, 10, 15...). You can combine steps with ranges: 10-50/10 * * * * fires at minutes 10, 20, 30, 40, and 50. The value before the slash is the starting point (or range), and the value after is the step increment.
Common Cron Schedules
Below is a reference table of the most frequently used cron expressions. You can click any of the quick presets in the tool above to load these directly into the builder.
| Expression | Schedule |
|---|---|
| * * * * * | Every minute |
| */5 * * * * | Every 5 minutes |
| */15 * * * * | Every 15 minutes |
| */30 * * * * | Every 30 minutes |
| 0 * * * * | Every hour (at minute 0) |
| 0 */2 * * * | Every 2 hours |
| 0 */6 * * * | Every 6 hours |
| 0 0 * * * | Daily at midnight |
| 0 12 * * * | Daily at noon |
| 0 9 * * 1-5 | Every weekday at 9:00 AM |
| 0 17 * * 1-5 | Every weekday at 5:00 PM |
| 0 8 * * 1 | Every Monday at 8:00 AM |
| 0 0 * * 0 | Every Sunday at midnight |
| 0 0 1 * * | First of every month at midnight |
| 0 0 1 1 * | January 1st at midnight (yearly) |
| 0 0 * * 1,3,5 | Mon, Wed, Fri at midnight |
| 30 4 1,15 * * | 1st and 15th of month at 4:30 AM |
| 0 9-17 * * 1-5 | Every hour from 9 AM to 5 PM, weekdays |
Cron in Modern DevOps
While cron originated on Unix workstations, its scheduling syntax has been adopted by nearly every orchestration and automation platform in use today. The syntax is the same five-field format, though some platforms extend it with minor variations.
Kubernetes CronJobs
Kubernetes uses standard five-field cron syntax in its CronJob resource. A CronJob creates a Job on the given schedule, which then spins up a Pod to execute the task. The timezone defaults to the timezone of the kube-controller-manager, which is usually UTC. Since Kubernetes 1.27, the timeZone field lets you specify an IANA timezone directly in the CronJob spec.
GitHub Actions
GitHub Actions supports schedule triggers using cron syntax. Schedules run in UTC and have a minimum interval of 5 minutes. During periods of heavy load, GitHub may delay or skip scheduled runs — so time-critical workflows need additional safeguards.
AWS EventBridge (CloudWatch Events)
AWS uses a six-field cron format that adds a Year field at the end: cron(0 9 ? * MON-FRI *). The question mark ? replaces the wildcard for day-of-month or day-of-week when the other is specified. AWS also supports rate expressions (rate(5 minutes)) as a simpler alternative for fixed intervals.
Vercel Cron Jobs
Vercel allows you to define cron schedules in vercel.json to trigger serverless functions. It uses standard five-field cron syntax with schedules running in UTC. This is useful for background tasks like rebuilding caches, sending digests, or refreshing data.
Six-Field Cron (with Seconds)
Some systems like Spring Scheduler and Quartz add a seconds field at the beginning, making it a six-field expression: seconds minute hour day-of-month month day-of-week. If you encounter a cron expression with six fields, the first field is almost certainly seconds. This builder focuses on the standard five-field format used by crontab, Kubernetes, and GitHub Actions.
Common Cron Mistakes
Even experienced engineers make these mistakes. If your cron job is not firing when you expect, check this list first.
Forgetting About Timezones
The single most common source of cron confusion. System cron uses the server's local timezone. Kubernetes defaults to the controller-manager's timezone (usually UTC). AWS EventBridge uses UTC. GitHub Actions uses UTC. If your server is in America/New_York but you wrote 0 9 * * * expecting UTC, your job runs at 9 AM Eastern, not 9 AM UTC. Always verify the timezone of your scheduler.
"Every Day" vs. "Every Weekday"
0 9 * * * fires every day, including Saturday and Sunday. If you only want business days, you need 0 9 * * 1-5. This mistake is especially costly for alerting, reporting, or billing jobs that should only run during business hours.
Day-of-Week Indexing
On most systems, Sunday is 0 and Saturday is 6. But some implementations treat Sunday as 7 (which is also valid on Linux cron). Some systems like AWS use three-letter names (MON, TUE). If you are switching between platforms, double-check which convention they use.
The Midnight Stampede
Everyone schedules their batch jobs at 0 0 * * *. On shared infrastructure, this creates a thundering herd at midnight UTC. Database backups, report generation, log rotation, and cache rebuilds all compete for resources at the same instant. Stagger your jobs: run backups at 15 2 * * * (2:15 AM) and reports at 30 3 * * * (3:30 AM) instead of cramming everything into midnight.
Overlapping Runs
If your job takes 10 minutes to complete but is scheduled every 5 minutes, you will have overlapping instances. Standard cron does nothing to prevent this — it just launches a new process on schedule regardless of whether the previous run finished. Use a lock file, a PID check, or a tool like flock to prevent concurrent execution. Kubernetes CronJobs handle this with the concurrencyPolicy field.
Cron Alternatives
Cron is ubiquitous, but it is not always the best tool for the job. Here are the main alternatives and when to consider them.
systemd Timers
On modern Linux distributions, systemd timers offer more features than cron: calendar-based scheduling with timezone support, randomized delays to avoid thundering herds, persistent timers that catch up on missed runs after a reboot, and dependency management with other systemd units. The tradeoff is more verbose configuration compared to a single cron line.
The at Command
Unlike cron (which handles recurring schedules), at runs a command once at a specified future time. Useful for one-off deferred tasks like "restart this service at 2 AM tonight" without creating a permanent schedule entry.
Task Schedulers (Celery Beat, APScheduler)
Application-level schedulers like Celery Beat (Python) and APScheduler integrate directly into your codebase. They support cron-style schedules, interval-based scheduling, and one-shot jobs, with the added benefit of database-backed persistence and distributed locking. They are the right choice when your scheduled tasks are tightly coupled to your application logic.
Managed Cron Services
Cloud providers offer managed alternatives: AWS EventBridge Scheduler, Google Cloud Scheduler, and Azure Logic Apps. These provide monitoring dashboards, automatic retries, dead-letter queues, and IAM-based access control out of the box. They eliminate the "which server is this cron running on?" problem that plagues traditional cron setups.
FAQ
What is cron syntax?
Cron syntax is the five-field time format used to define recurring schedules on Unix-like systems. The fields represent minute, hour, day of month, month, and day of week. Each field accepts numbers, wildcards (*), ranges (1-5), lists (1,3,5), and step values (*/5). Together, the five fields specify exactly when a scheduled task should execute.
What timezone does cron use?
By default, cron uses the system timezone of the machine it runs on. On most Linux servers, this is configured in /etc/timezone or via the TZ environment variable. Cloud services like AWS, GitHub Actions, and Kubernetes typically default to UTC. Always verify which timezone your specific scheduler uses before deploying a schedule to production.
Can I schedule a cron job every 30 seconds?
Not with standard cron — the smallest granularity is one minute. The common workaround is to create two cron entries that fire at the same time, with the second one prefixed by a 30-second sleep: sleep 30 && /path/to/command. For true sub-minute scheduling, consider systemd timers, Celery Beat, or a dedicated process manager.
What is the difference between cron and crontab?
Cron is the daemon (background service) that continuously runs on the system and executes scheduled tasks. Crontab (short for "cron table") is the configuration file that lists which commands to run and when. You edit the crontab with crontab -e, and the cron daemon reads it to determine what to execute.
Does this cron builder tool work offline?
Yes. This tool runs entirely in your browser using vanilla JavaScript. Once the page loads, all parsing, validation, description generation, and next-run calculations happen locally. No data is ever sent to a server.