Tutorial

Run a cron job every hour.

The simplest way is 0 * * * * — fires at the top of every hour. The 0 in the minute field locks it to minute zero; the * in every other field means "any value."

The expression

0 * * * * /path/to/your/script.sh

Or use the macro shorthand, which works on most modern systems:

@hourly /path/to/your/script.sh

They're identical — @hourly expands to 0 * * * *.

Variations

ExpressionMeaning
0 * * * *Every hour at :00
30 * * * *Every hour at :30
0 */2 * * *Every 2 hours (0, 2, 4, 6, …)
0 */3 * * *Every 3 hours (0, 3, 6, 9, …)
0 9-17 * * *Every hour from 9 AM to 5 PM
0 9-17 * * 1-5Every hour during business hours, weekdays only

Platform-specific examples

Linux crontab

@hourly /usr/local/bin/refresh-cache.sh

AWS EventBridge

AWS doesn't support macros. Use the explicit form:

cron(0 * ? * * *)

GitHub Actions

on:
  schedule:
    - cron: '0 * * * *'

Kubernetes CronJob

schedule: "0 * * * *"

Common mistakes

Don't use * * * * * — that fires every minute, not every hour. The minute field must be 0 (or a specific minute) for hourly cadence.

Be careful with */2 in the hour field. 0 */2 * * * fires at midnight, 2 AM, 4 AM, ... 10 PM — that's a 23-hour gap at midnight on month boundaries because the count resets. Usually fine; just be aware.

Distributing load across multiple servers

If 100 servers all run @hourly, they all fire at :00 — which can overwhelm shared backends. Two fixes:

  • Stagger by minute: server 1 uses 3 * * * *, server 2 uses 7 * * * *, etc.
  • Use Jenkins' H syntax (Jenkins-only) which automatically hashes the offset per job.
Related

Continue reading.