0 * * * * — What does this cron expression mean?
0 * * * * is the hourly cron job, identical to @hourly. The single 0 in the minute field is the whole schedule: every hour, the job fires when the clock reads :00. That is simple, but it also means your job competes with every other hourly job on the same machine, cluster or CI provider in that one minute.
0 * * * *
Run the job once every hour, exactly on the hour (minute 0): 00:00, 01:00, 02:00 … 23:00.
Frequency: 1 run per hour, 24 per day. cronstrue reads it as “Every hour”.
Open 0 * * * * in the Cron BuilderField-by-field breakdown
0
Minute
0–59
*
Hour
0–23
*
Day of month
1–31
*
Month
1–12
*
Day of week
0–6
- Minute0 — only at minute 0, the top of the hour.
- Hour* — every hour, 0 through 23.
- Day of month* — every day of the month.
- Month* — every month.
- Day of week* — every day of the week.
Next run times
Example: if it is Monday, 5 Jan 2026, 09:07 UTC, the next runs of 0 * * * * (UTC) are:
- #1Mon, 5 Jan 2026, 10:00 UTC
- #2Mon, 5 Jan 2026, 11:00 UTC
- #3Mon, 5 Jan 2026, 12:00 UTC
- #4Mon, 5 Jan 2026, 13:00 UTC
- #5Mon, 5 Jan 2026, 14:00 UTC
Live times from your current clock replace this example once the page loads. Cron uses the scheduler's timezone; most cloud servers, GitHub Actions and AWS EventBridge rules use UTC.
0 * * * * in Quartz, AWS, GitHub Actions, Kubernetes and systemd
Crontab (Linux / macOS)
0 * * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1Standard 5-field syntax used by Vixie cron, cronie, busybox crond and most libraries (node-cron, APScheduler, robfig/cron).
Quartz (6 and 7 fields)
0 0 * * * ?
0 0 * * * ? *
# Spring @Scheduled
@Scheduled(cron = "0 0 * * * *")Generators such as CronMaker output 0 0 0/1 1/1 * ? * for “every hour”. It is the same schedule written verbosely: 0/1 is every hour from 0 and 1/1 is every day from the 1st.
AWS EventBridge
cron(0 * * * ? *)
# interval alternative
rate(1 hour)Note the singular unit: rate(1 hour), not rate(1 hours). AWS rejects the plural when the value is 1.
GitHub Actions
on:
schedule:
# Every hour, evaluated in UTC
- cron: '0 * * * *'GitHub's documentation warns that load is highest at the start of every hour, and runs may be delayed or dropped. If “roughly hourly” is fine, prefer a random minute such as 23 * * * *.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: every-hour
spec:
schedule: "0 * * * *"
timeZone: "Etc/UTC"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 600
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: job
image: alpine:3.20
command: ["/bin/sh", "-c", "echo running"]Kubernetes accepts @hourly too. A 10-minute deadline keeps a late Job useful without risking a pile-up.
systemd timer
# /etc/systemd/system/myjob.timer
[Unit]
Description=Every hour
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.targethourly means *-*-* *:00:00. Add RandomizedDelaySec=5min if many timers share the same host.
When to use every hour
- Rolling up raw events into hourly aggregates.
- Refreshing exchange rates, weather or other data that changes on an hourly cadence.
- Running log shippers or upload jobs that batch an hour's worth of files.
- Pruning temporary files and caches before they fill a small disk.
Common pitfalls with 0 * * * *
:00 is the most crowded minute everywhere
Hourly jobs from every team, every package and every tenant land on :00. On shared databases this produces an hourly latency spike; on CI providers it means queueing. Jenkins introduced the H symbol (H * * * *) for exactly this reason: it picks a stable pseudo-random minute per job. In plain cron, pick a minute yourself.
# Everyone's hourly job
0 * * * *
# Same frequency, off the crowded minute
23 * * * *Hourly is not “60 minutes after the last run”
Cron fires at wall-clock :00. If the server is down from 10:58 to 11:02, the 11:00 run is lost, not delayed. If a run must not be skipped, use a scheduler that catches up (systemd Persistent=true, anacron) or make the next run process everything since the last success.
0 * * * * vs * 0 * * *
Swapping the first two fields changes everything: * 0 * * * runs every minute between 00:00 and 00:59, 60 times a day, and never at any other hour.
Related cron expressions
Every 15 minutes
*/15 * * * *
At minute 15 of every hour
15 * * * *
Every 4 hours
0 */4 * * *
Every 6 hours
0 */6 * * *
Need a different schedule? Paste 0 * * * * into the Cron Builder and edit it, browse all cron expressions, read the cron syntax guide or copy from the cron examples list.
Frequently Asked Questions
What does 0 * * * * mean in cron?▾
Once every hour at minute 0. The job runs at 00:00, 01:00, 02:00 and so on, 24 times a day. It is identical to @hourly.
What is 0 0 0/1 1/1 * ? * in cron?▾
It is a 7-field Quartz expression (seconds, minutes, hours, day-of-month, month, day-of-week, year) meaning every hour on the hour, the same as 0 * * * * in crontab. Tools such as CronMaker generate this verbose form; 0 0 * * * ? is the shorter Quartz equivalent.
How do I write an hourly cron job for AWS?▾
Use cron(0 * * * ? *) to run at the top of every hour UTC, or rate(1 hour) to run every 60 minutes from when the rule was created.