* * * * * │ │ │ │ │ │ │ │ │ └── day of week (0-6, Sunday=0) │ │ │ └──── month (1-12) │ │ └────── day of month (1-31) │ └──────── hour (0-23) └────────── minute (0-59)
The order is fixed and there's no mnemonic for it. You just have to remember that minute comes before hour. Write hour-then-minute once, out of habit from some other config format, and the job fires at the wrong time every day. It's an annoying bug to spot because the schedule looks right at a glance.
Schedules people copy-paste most
0 * * * *: every hour, on the hour*/15 * * * *: every 15 minutes0 0 * * *: once a day, at midnight0 9 * * 1-5: 9am, Monday through Friday0 0 1 * *: midnight on the 1st of every month0 0 * * 0: midnight every Sunday
Setting both day fields gives you either, not both
This is the sharpest edge in cron. If both the day-of-month and day-of-week fields are restricted (neither is *), most cron implementations run the job when either one matches. 0 0 15 * 5 runs at midnight on the 15th of every month and also every Friday. It does not mean “the 15th, if it's a Friday.” Cron can't express that intersection, so if that's what you need, put the check in your application code.
Step values and ranges combine
10-30/5 in the minute field means every 5 minutes between minutes 10 and 30: 10, 15, 20, 25, 30. That covers “every 5 minutes during business hours” style schedules without a second cron line.