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
*

Next 5 Runs

  • in 1m 35s
  • in 1h 1m
  • in 2h 1m
  • in 3h 1m
  • in 4h 1m

* Tools

Code & Implementations

nodejs
const cron = require('node-cron');

// Schedule the task to run at minute 0 of every hour
cron.schedule('0 * * * *', async () => {
    console.log(`[${new Date().toISOString()}] Initiating hourly cache invalidation...`);
    try {
        await clearExpiredSessions();
        console.log('Hourly cache invalidation completed.');
    } catch (error) {
        console.error('Unexpected execution error during hourly task:', error);
    }
});

async function clearExpiredSessions() {
    // Production session clearing logic goes here
    return Promise.resolve();
}
Setup notes

Install the 'node-cron' package using npm or yarn, then run this script as a daemon or background process using a process manager like PM2.

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

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

Was this helpful?

Last verified: