Quick answer
The cron expression for every 2 hours is 0 */2 * * *. The 0 fixes the minute, and */2 in the hour field keeps every second hour from 0 to 23, so the job runs at 00:00, 02:00, 04:00 through 22:00: 12 times a day. For odd hours (01:00, 03:00 … 23:00) use 0 1-23/2 * * *.
- Live next runs
- Any time zone
- Field-by-field breakdown
- Seven platform snippets
- Daylight saving aware
How to use this schedule
- 1Copy
0 */2 * * *with the Copy expression button. - 2Check Next runs in your time zone to confirm it fires when you expect, including around daylight saving changes.
- 3Pick your platform under Use it on your platform and copy the ready-made crontab line, workflow, manifest or timer.
- 4Need a different time or day? Click Customize to open it in the cron expression generator and change any field.
What does 0 */2 * * * mean?
Two fields do the work. The minute is fixed at 0, so each run happens on the hour. The hour field */2 steps through 0–23 in twos starting at 0, which leaves the even hours. Forget either part and the schedule changes dramatically:
| Expression | What actually happens |
|---|---|
0 */2 * * * | 00:00, 02:00 … 22:00, 12 runs a day |
0 1-23/2 * * * | 01:00, 03:00 … 23:00, 12 runs a day |
*/2 * * * * | Every 2 minutes, 720 runs a day |
* */2 * * * | Every minute of every even hour, 720 runs a day |
The bottom two rows are the most common copy-paste accidents with this schedule. The step has to sit in the second field, with a number in the first.
Does every 2 hours count from when the job starts?
No. Cron has no memory of previous runs; it only matches clock times. The */2 step counts from hour 0 every day, so the runs are always at the same twelve times, whether you installed the job at 09:13 or 22:59. Because 24 divides evenly by 2, the gap from 22:00 to the next midnight is also two hours.
To anchor the rhythm somewhere else, choose the minute and the parity of the hours:
15 */2 * * *runs at 00:15, 02:15 … 22:1530 1-23/2 * * *runs at 01:30, 03:30 … 23:30, which includes 09:300 8-20/2 * * *limits the runs to 08:00 through 20:00
Twelve runs a day is a comfortable cadence for syncing reference data, rebuilding search indexes or rotating reports. If that is still too often, every 3 hours gives eight runs and every 6 hours gives four.
What does each field in 0 */2 * * * mean?
| Field | Value | Allowed | Meaning |
|---|---|---|---|
| Minute | 0 | 0–59 | at minute 0 (on the hour) |
| Hour | */2 | 0–23 | every 2 hours: 00:00, 02:00, 04:00 … 22:00 |
| Day of month | * | 1–31 | every day of the month |
| Month | * | 1–12, JAN–DEC | every month |
| Day of week | * | 0–7 (0 and 7 are Sunday), SUN–SAT | every day of the week |
Read together: At minute 0 of every even hour (00:00, 02:00 … 22:00), every day.
How do I adjust 0 */2 * * * to my own schedule?
Small edits to 0 */2 * * * cover most real-world needs:
| Expression | What it does |
|---|---|
0 1-23/2 * * * | Every 2 hours on odd hours (01:00, 03:00 … 23:00) |
30 */2 * * * | Every 2 hours at half past (00:30, 02:30 … 22:30) |
0 8-20/2 * * * | Every 2 hours from 08:00 to 20:00 |
0 */2 * * 1-5 | Every 2 hours on weekdays only |
0 */3 * * * | Every 3 hours |
Need something else? Click Customize at the top of the page to open this schedule in the cron expression generator and change any field.
Related schedules: Every hour · Every 3 hours · Every 6 hours · Every 2 minutes
Browse all schedules in the cron schedule library.
How do I run 0 */2 * * * in crontab, GitHub Actions, Kubernetes and the cloud?
| Platform | Write it as | Time zone |
|---|---|---|
| Linux crontab | 0 */2 * * * | Server's time zone; CRON_TZ= in cronie |
| GitHub Actions | - cron: "0 */2 * * *" | UTC by default; add timezone: (IANA name) |
| Kubernetes CronJob | schedule: "0 */2 * * *" | Set timeZone: (1.27+) |
| Cloudflare Workers | 0 */2 * * * | UTC only; numbers weekdays from 1 = Sunday, so use names |
| Vercel Cron Jobs | 0 */2 * * * | UTC only; more than once a day needs Pro (Hobby: once a day) |
| AWS EventBridge Scheduler | cron(0 */2 * * ? *) | Takes a time zone; legacy scheduled rules are UTC only |
| systemd timer | OnCalendar=*-*-* 0/2:00:00 | Add a zone after the time, e.g. Europe/London |
In a crontab (crontab -e), the full line looks like this:
0 */2 * * * /path/to/job.sh >> /var/log/job.log 2>&1The live panel at the top of the page builds complete, copy-ready files for each platform (workflow, CronJob manifest, wrangler.toml, vercel.json, AWS CLI and systemd units) and can shift the schedule to UTC for platforms that need it.
What can go wrong with 0 */2 * * *?
*/2 * * * *is every 2 minutes, not every 2 hours. The step belongs in the second field, with a fixed minute in the first.- Leaving the minute as
*(* */2 * * *) runs the job every minute for a whole hour, every other hour: 720 runs a day instead of 12. - In America/New_York the spring-forward night has no 02:00, so a local-time
0 */2 * * *job runs 11 times that day. A server on UTC always gets 12. - If one run can last longer than two hours, protect it with
flock -n /tmp/job.lock your-commandso runs don't pile up. - In a zone with daylight saving time, a schedule with
*in the minute or hour field follows the wall clock: the spring-forward night loses an hour of runs and the fall-back night repeats one. Servers on UTC never see this.
Frequently asked questions
Last updated by the Playxoft engineering team.