Blog

How to write a cron expression

The five cron fields, the special characters that combine them, common schedules you can copy, and the platform differences that cause jobs to run at the wrong time.

February 7, 2026

You set the nightly backup to run “at 2 AM”, checked it the next morning, and found it had run every minute from 2:00 to 2:59. Sixty backups and one full disk later, cron syntax seems worth learning properly. It only has five fields.

What cron is

Cron is the job scheduler built into Unix-like systems such as Linux and macOS. It runs commands or scripts at set times: database backups, log rotation, scheduled emails, scrapers and so on. CI systems, Kubernetes and cloud schedulers borrowed the same syntax.

A cron expression is the short string that says when a job runs. For example, 0 */6 * * 1-5 means “at minute 0 of every sixth hour, Monday to Friday”. That’s 00:00, 06:00, 12:00 and 18:00 on weekdays.

The five fields

A standard expression has five fields separated by spaces:

Text
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-7, 0 and 7 are Sunday)
│ │ │ │ │
* * * * *

Each field holds a single value, a range, a list, a step or an asterisk. Most implementations also accept names such as JAN or MON in the month and day-of-week fields.

Special characters

Asterisk (*)

Matches every value. * * * * * runs every minute. This is how the backup above went wrong: * 2 * * * means “every minute of the 2 AM hour”. What it needed was 0 2 * * *.

Slash (/)

Sets a step. */15 in the minute field runs at 0, 15, 30 and 45 past the hour. To start somewhere else, put a range before the step: 5-59/15 runs at 5, 20, 35 and 50. Some schedulers, such as Quartz, also accept the shorter 5/15.

Hyphen (-)

Sets a range. 1-5 in the day-of-week field is Monday to Friday. Ranges take steps too: 1-5/2 is Monday, Wednesday and Friday.

Comma (,)

Makes a list. 1,15 in the day-of-month field runs on the 1st and 15th. Lists can include ranges: 1,5,10-15.

Common schedules

Text
* * * * *      every minute
0 * * * *      every hour, on the hour
0 0 * * *      every day at midnight
0 9 * * 1      every Monday at 09:00
30 8 * * 1-5   every weekday at 08:30
0 0 1 * *      the first day of every month at midnight
*/15 * * * *   every 15 minutes
0 */6 * * *    every 6 hours
0 2 * * 0      every Sunday at 02:00

Many systems also accept shortcuts such as @hourly, @daily, @weekly, @monthly and @reboot (run once at startup).

Cron on different platforms

The five-field format is the common core, but platforms extend it. Spring and Quartz add a seconds field at the start, and AWS adds a year field at the end.

GitHub Actions
on:
  schedule:
    - cron: "0 6 * * 1-5"
Kubernetes CronJob
spec:
  schedule: "*/30 * * * *"
AWS EventBridge (six fields, with year)
cron(0 12 * * ? *)
crontab
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Differences worth checking in your platform’s docs:

  • Time zone. crontab uses the server’s time zone. GitHub Actions and AWS EventBridge cron expressions use UTC. Kubernetes uses the controller’s time zone unless you set timeZone.
  • Minimum interval. GitHub Actions runs scheduled workflows at most every 5 minutes, and runs can start late when load is high.
  • Extra syntax. AWS requires ? in either the day-of-month or day-of-week field. Quartz numbers days of the week 1 to 7 starting on Sunday.

Why a job runs at the wrong time

Cron is almost never wrong. The expression just means something other than what you expected. Three common traps:

  • Steps follow the field’s range, not today’s date. 0 0 */2 * * runs on the 1st, 3rd, 5th and so on, then the 31st and the 1st of the next month back to back. It is not “every two days from now”.
  • Day of month and day of week are combined with OR. In standard cron, 0 0 13 * 5 runs on every 13th and every Friday, not only on Friday the 13th.
  • The time zone is not the one you assumed. A job set for 0 9 * * * on a UTC server runs at 09:00 UTC.

How to use the cron generator

  1. Open the cron generator and type an expression, or pick one of the presets such as “Every 5 minutes” or “Every weekday at 9 AM”.
  2. Read the plain-language explanation under the input, for example “At 9:00 AM, Monday through Friday.”
  3. Check the next 5 runs, shown in your browser’s time zone.
  4. Copy the expression into your crontab, workflow file or scheduler.

It runs in your browser and handles standard five-field expressions: numbers, *, ranges, lists and steps, including steps on a range such as 1-5/2. The next-run preview follows standard cron rules. Steps count from the start of the range, 7 counts as Sunday, and when both day fields are set, a day matching either one runs. That makes the preview a handy way to catch the traps above before they reach production.

Names like MON or JAN, @ shortcuts such as @daily, and seconds or year fields aren’t supported. Write those schedules out in numbers, or check them against your platform’s docs.

Need data from a webpage as JSON?

PulpMiner turns any public page into structured JSON and can save it as a live API. See it work on a demo page, no sign-up.

Try it on a demo page