Code & Dev
Free Cron Expression Generator Online
Generate cron expressions visually and see next execution times in plain English.
What is cron and where is it used?
Cron is a time-based job scheduler that originated in Unix operating systems in the 1970s. Its name comes from the Greek word chronos (time). The cron daemon — a background process that runs continuously — reads configuration files called crontabs (cron tables), checks them against the current time every minute, and executes any commands whose schedule matches. For decades, cron was the de facto standard for automating repetitive server tasks: rotating logs, backing up databases, sending digest emails, and pruning stale records.
What began as a Unix utility has since grown into the universal scheduling primitive of the entire software industry. Today, cron expression syntax is used in an enormous range of platforms and services, far beyond the original Unix daemon:
Even tools that do not expose raw cron syntax — such as Airflow DAGs, dbt Cloud job schedules, and Celery Beat — use cron expressions internally and accept them in their configuration. Fluency with cron syntax is genuinely one of the most transferable skills in backend and DevOps engineering.
Anatomy of a cron expression
A standard Unix cron expression consists of five fields separated by spaces. Each field controls a different unit of time. The fields are evaluated left to right, and a job runs only when all five fields match the current time simultaneously.
Reading the expression 30 9 * * 1-5 from left to right: minute 30, hour 9, any day of month, any month, weekdays Monday through Friday. Combined: "Run at 09:30 every weekday." The asterisk * in field 3 and 4 means "match any value", so the day-of-month and month constraints do not restrict which days the job runs — only the day-of-week field does.
Some platforms — notably AWS EventBridge and Quartz Scheduler (Java) — extend the standard five-field format to six or seven fields by adding a seconds field at the start and optionally a year field at the end. Always check the documentation of the specific platform you are targeting, because the same string may be interpreted differently across systems.
Cron special characters explained
Each of the five fields accepts a set of special characters in addition to numeric values. These characters dramatically expand the expressiveness of cron expressions without requiring one entry per match.
| Character | Name | Example | Meaning |
|---|---|---|---|
| * | Wildcard | * in Hour | Matches every possible value in that field. * in the hour field means "every hour". |
| , | List | 1,15 in Minute | Matches a list of specific values. 1,15 means "at :01 and at :15". |
| - | Range | 1-5 in Day of Week | Matches a range of values inclusive. 1-5 means Monday through Friday. |
| / | Step | */15 in Minute | Matches at intervals. */15 means every 15 minutes; 0/30 means every 30 minutes starting at :00. |
| ? | No specific value | ? in Day of Month | Supported in some systems (Quartz, AWS). Means "no specific value" — used to leave day-of-month or day-of-week unspecified when the other is set. |
Lists and ranges can be combined freely. The expression 0 9,12,17 * * 1-5 runs at 9 AM, noon, and 5 PM on every weekday — three executions per day, five days a week. Step values can be applied to ranges as well: 0-30/5 * * * * runs every five minutes within the first half of every hour.
10 essential cron expressions every developer should know
These expressions cover the vast majority of real-world scheduling needs. Copy them directly into your crontab, GitHub Actions workflow, or cloud scheduler configuration.
| Expression | Meaning |
|---|---|
| * * * * * | Every minute — useful for health-check pings and rapid polling tasks during development |
| 0 * * * * | Every hour on the hour — common for aggregation jobs, reporting roll-ups, and cache warming |
| 0 0 * * * | Every day at midnight UTC — classic for daily digest emails, database backups, and log rotation |
| 0 9 * * 1-5 | At 09:00 on every weekday (Mon–Fri) — for business-hours notifications and scheduled reports |
| 0 0 * * 0 | Every Sunday at midnight — weekly cleanup tasks, database vacuum, analytics export |
| */15 * * * * | Every 15 minutes — frequent polling, metrics collection, and queue drain checks |
| 0 0 1 * * | First day of every month at midnight — monthly invoice generation, billing cycles |
| 0 2 * * * | Every day at 2:00 AM UTC — off-peak maintenance window for migrations and data imports |
| 30 23 * * 5 | At 23:30 every Friday — end-of-week report generation before the weekend |
| 0 0 1 1 * | At midnight on January 1st — annual reset jobs, year-over-year analytics initialisation |
How to test and validate a cron expression
A cron expression that looks correct can still fire at the wrong time. Validating before you deploy saves the kind of incident where a nightly backup runs every minute at 3 AM. There are three layers to check:
Confirm the expression parses without errors on the target platform. A five-field expression valid in Unix cron will be rejected by AWS EventBridge (which requires six fields with a ? placeholder). Use this generator — it validates as you type and flags field-range errors in real time.
Calculate the next 5–10 scheduled fire times from now. If "every weekday at 9 AM" shows a Saturday, the day-of-week field is wrong. This tool shows the next 10 fire times in plain English so you can visually confirm the schedule before committing it to a config file.
Verify the fire times in the timezone the scheduler actually uses, not your local clock. Most cloud schedulers default to UTC. Convert "next run at 2026-05-12 09:00 UTC" to your local time with the Timestamp Converter to confirm it lands in the right window.
Quartz and Spring cron syntax
Quartz Scheduler (widely used in Java applications) and Spring's @Scheduled annotation both extend standard Unix cron with a mandatory seconds field, giving six or seven total fields. This is the most common source of confusion when moving expressions between Unix cron and a Java stack.
| Format | Field order | Example | Meaning |
|---|---|---|---|
| Unix cron | min hr dom mon dow | 0 9 * * 1-5 | At 09:00 every weekday |
| Quartz / Spring | sec min hr dom mon dow [year] | 0 0 9 * * MON-FRI | At 09:00:00 every weekday |
| AWS EventBridge | min hr dom mon dow year | 0 9 ? * MON-FRI * | At 09:00 every weekday (? required) |
Quartz also uses ? as a "no specific value" placeholder — required in either the day-of-month or day-of-week field when the other is constrained (since Quartz treats them as AND, not OR). Spring's @Scheduled(cron = "...") follows Quartz syntax but drops the optional year field. If your Spring job isn't firing when expected, check whether you accidentally used a five-field Unix expression instead of the required six-field Quartz format.
Cron vs other scheduling approaches
Cron is the right tool for many tasks, but not all of them. Understanding where it fits in the broader landscape of scheduling mechanisms will help you make the right architectural choice.
setInterval runs inside a running process and stops when the process dies. It has no persistence, no timezone awareness, and no catch-up on missed executions. Use setInterval only for short-lived, in-process periodic work like polling an internal state every few seconds. Use cron when the task must survive process restarts.
A common pattern is calling setTimeout recursively to create a "polling loop". Like setInterval, this lives and dies with the process and offers no scheduling precision (drift accumulates). For background jobs that need reliable cadence, a process-external scheduler like cron is more robust.
Message queues with delayed delivery — such as SQS message timers, RabbitMQ dead-letter queues, or BullMQ delayed jobs — are better when you need per-item scheduling (e.g. "send a reminder email 24 hours after user signup"). Cron is calendar-driven and applies to all items equally; message queues are entity-driven and apply individually. Use both together: a cron job enqueues messages, and workers process them.
Tools like pg_cron (PostgreSQL extension), Sidekiq-Cron (Ruby), Celery Beat (Python), and Agenda (Node.js) store job schedules in a database and support dynamic schedule changes without redeploying configuration files. They are superior to system cron when schedule management needs to be part of the application itself — for example, when users can configure their own notification schedules.
The general rule: cron is ideal for system-level, calendar-driven, stateless tasks. If the job needs to know about individual records, retry failed items, fan out to many workers, or be managed dynamically, reach for a message queue or a database-backed scheduler instead.
Timezone pitfalls with cron
Timezone handling is the most operationally dangerous aspect of cron scheduling, and it catches even experienced engineers off guard. The core issue is that the traditional Unix cron daemon uses the system clock of the server it runs on, with no awareness of the timezone in which your users or business operations are located. If your server is in UTC but your business is in New York, a cron job scheduled for 0 9 * * * will run at 9 AM UTC — which is 4 AM or 5 AM New York time depending on DST.
Daylight Saving Time (DST) introduces a second layer of complexity. When clocks spring forward by one hour, there is a 60-minute gap during which the local time never exists — any cron job scheduled to run during that gap simply does not fire. When clocks fall back by one hour, there is a 60-minute overlap during which the local time exists twice — a cron job scheduled in that window may run twice. These bugs are particularly dangerous because they only surface twice a year, often at off-peak hours when no one is watching dashboards.
Recommendation: Always write cron expressions in UTC and configure your scheduler explicitly to use UTC, regardless of where your users are. Most modern cloud schedulers — AWS EventBridge, GCP Cloud Scheduler, GitHub Actions — allow you to specify the timezone for each job. When you must use a non-UTC timezone, use a named IANA timezone (e.g. America/New_York) rather than a fixed UTC offset like UTC-5, because named timezones include DST rules while fixed offsets do not.
A related pitfall affects containerised workloads. Docker containers inherit the UTC timezone of the host by default, which is usually correct — but if your container image explicitly sets a local timezone via the TZ environment variable or by copying /etc/localtime, your cron daemon inside the container will use that timezone. When you move the container across cloud regions or providers, the timezone travels with it and may produce unexpected execution times. Keep container images timezone-agnostic and always pass timezone configuration as an environment variable at runtime.
Kubernetes CronJobs offer a timeZone field (added in Kubernetes 1.27, graduated to stable in 1.29) that lets you specify an IANA timezone per CronJob. Before that field was available, teams worked around the UTC-only limitation by adjusting their cron expressions to compensate for the offset — a fragile approach that broke every time DST changed. If you are on Kubernetes 1.27 or later, always use the timeZone field rather than adjusting expressions manually.
FAQ
Common questions
What is a cron expression?
A cron expression is a string of 5 (or 6) fields that defines when a scheduled task should run. The fields represent minute, hour, day-of-month, month, and day-of-week — separated by spaces. For example, "0 9 * * 1-5" means "at 09:00 every weekday". Cron is used in Unix/Linux systems, cloud schedulers (AWS EventBridge, GCP Cloud Scheduler), GitHub Actions, and most backend job frameworks.
What do the 5 cron fields mean?
Field 1 — Minute (0-59): which minute of the hour. Field 2 — Hour (0-23): which hour of the day (0 = midnight). Field 3 — Day of month (1-31): which day of the month. Field 4 — Month (1-12 or JAN-DEC): which month. Field 5 — Day of week (0-6 or SUN-SAT, where 0 = Sunday): which day of the week. An asterisk (*) means "every value" for that field.
What does the asterisk (*) mean in a cron expression?
An asterisk (*) is a wildcard meaning "every valid value". In the minute field, * means "every minute". In the month field, * means "every month". "* * * * *" means "every minute of every hour of every day". It's the most permissive value for any field.
What is the difference between */5 and 0-59/5?
Both mean "every 5 units", but the step syntax */5 is shorthand for the full range with a step — equivalent to 0-59/5 in the minute field. "*/5" in the minute field means "at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55". The slash (/) means "step" or "every N".
Can I specify multiple values or ranges in one field?
Yes. Use commas for lists: "1,15,30" in the minute field means "at minutes 1, 15, and 30". Use hyphens for ranges: "1-5" in the day-of-week field means "Monday through Friday". Combine them: "0,30 9-17 * * 1-5" means "at :00 and :30 of each hour from 9am to 5pm, weekdays only".
What timezone does cron use?
Traditional cron on Linux/Unix runs in the system timezone, which is usually UTC on servers. Cloud schedulers (AWS EventBridge, GCP Cloud Scheduler) let you specify a timezone explicitly. When in doubt, always write cron expressions in UTC and convert to local time in your documentation — this prevents daylight saving time bugs.
What is the difference between day-of-month and day-of-week?
Day-of-month (field 3) targets a specific calendar day: "15" means "on the 15th of every month". Day-of-week (field 5) targets a day name: "1" means "every Monday". When both are specified (not *), most cron implementations run the job if EITHER condition is true. To run on "the first Monday of the month" requires additional scripting logic — cron alone cannot express that.
How do I run a job every 30 minutes?
"*/30 * * * *" runs at minute 0 and 30 of every hour (midnight, 00:30, 01:00, 01:30, ...). Alternatively "0,30 * * * *" is identical and more explicit. Do not use "30 * * * *" — that means "at minute 30 of every hour", which is once per hour, not every 30 minutes.
Does this generator support 6-field cron with seconds?
The standard Unix cron format has 5 fields (minute to day-of-week). Some systems like Spring Framework (@Scheduled), Quartz Scheduler, and AWS cron rules support a 6th field for seconds at the beginning. This generator produces standard 5-field expressions compatible with crontab, GitHub Actions, GCP, and most schedulers. Check your platform's documentation if you need sub-minute precision.
More in Code & Dev