Run Jobs Hourly at the Top of the Hour | CronBase

cron expression Standard
$ 0 * * * *

At the beginning of every hour.

This cron expression schedules a task to run exactly once per hour, specifically at the very beginning of the hour (minute zero). It is widely used in production environments for recurring tasks like generating hourly metrics, purging expired session caches, pulling external API updates, and rotating small log files.

Minute
0
Hour
*
Day of Month
*
Month
*
Day of Week
*
How it works

Next 5 Runs

  • in 7m 24s
  • in 1h 7m
  • in 2h 7m
  • in 3h 7m
  • in 4h 7m

* Tools

Code & Implementations

Bash
#!/usr/bin/env bash
# Hourly maintenance task with flock to prevent overlapping executions
set -euo pipefail

LOCKFILE="/var/lock/hourly_maintenance.lock"
exec 9>"$LOCKFILE"

if ! flock -n 9; then
    echo "Error: Another instance of the hourly job is still running." >&2
    exit 1
fi

echo "[$(date -u)] Starting hourly database cleanup..."
# Perform cleanup operation here
# e.g., pg_dump or temporary file removal
echo "[$(date -u)] Hourly cleanup completed successfully."
Setup notes

Save this script to /usr/local/bin/hourly-cleanup.sh, make it executable, and add '0 * * * * /usr/local/bin/hourly-cleanup.sh' to your crontab using 'crontab -e'.

Last verified:

Partner BetterStack

Monitor this schedule in production

Get alerted the moment this cron job fails, is late, or doesn't run. BetterStack tracks execution, duration, and output — no infrastructure required.

Platform Equivalents

AWS EventBridge

Standard cron expressions often need conversion for AWS EventBridge schedules.

EventBridge Rule
cron(0 * * * ? *)

Systemd Timer

OnCalendar*-*-* *:00:00

my-task.timer
[Unit]
Description=Timer for cron expression: 0 * * * *

[Timer]
OnCalendar=*-*-* *:00:00
Persistent=true

[Install]
WantedBy=timers.target

Last verified:

Frequently Asked Questions

How does `0 * * * *` handle Daylight Saving Time (DST) transitions?

Standard system cron runs on UTC to avoid DST anomalies. If your server is configured to local time, the job may execute twice during the autumn fallback or skip execution entirely during the spring spring-forward transition.

What is the difference between `0 * * * *` and `*/60 * * * *`?

In standard cron, both expressions execute at minute zero of every hour. However, `0 * * * *` is preferred for readability and explicit behavior, whereas step syntax like `*/60` can sometimes be interpreted differently depending on the specific cron daemon implementation.

How do I prevent multiple instances of this hourly job from running concurrently?

Use file locks (like `flock` in Bash), distributed locks (like Redis/Redlock in application code), or set `concurrencyPolicy: Forbid` in Kubernetes CronJobs to prevent a slow-running execution from overlapping with the next hour's run.

Can I run this job at a specific minute other than zero?

Yes. If you want to run the job hourly but avoid the "top-of-the-hour" rush, simply change the first field. For example, `15 * * * *` will run the job at 15 minutes past every hour, distributing resource load.

How can I test my `0 * * * *` schedule without waiting an hour?

For local testing, temporarily change the schedule to `*/1 * * * *` (every minute) or trigger the target script/command directly in your terminal to verify execution logic before deploying the hourly cron schedule.

* Explore

Related expressions you might need

Last verified:

Was this helpful?