How to Run a Job Every 3 Hours | CronBase
0 */3 * * * Every three hours, on the hour.
The `0 */3 * * *` cron expression schedules a task to run every three hours, precisely at the start of the hour. Executions occur eight times a day at midnight, 3:00 AM, 6:00 AM, 9:00 AM, noon, 3:00 PM, 6:00 PM, and 9:00 PM, typically configured in UTC.
- Minute
- 0
- Hour
- */3
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 36m 46s
- in 3h 36m
- in 6h 36m
- in 9h 36m
- in 12h 36m
* Tools
Code & Implementations
#!/usr/bin/env bash
set -euo pipefail
# Lockfile to prevent overlapping executions
LOCKFILE="/var/run/tri_hourly_job.lock"
# Run with flock to ensure exclusive execution
0 */3 * * * /usr/bin/flock -n "$LOCKFILE" /usr/local/bin/my-task.sh >> /var/log/my-task.log 2>&1 › Setup notes
Add this entry to your system crontab using 'crontab -e'. It utilizes flock to ensure that if a previous run is still active, the new run exits gracefully without overlapping.
const cron = require('node-cron');
const log = require('fancy-log');
// Schedule task to run every 3 hours (0 */3 * * *)
cron.schedule('0 */3 * * *', async () => {
log.info('Starting tri-hourly scheduled task...');
try {
await performTask();
log.info('Task completed successfully.');
} catch (error) {
log.error('Task failed with error: ', error);
}
}, {
scheduled: true,
timezone: 'UTC'
});
async function performTask() {
// Production task logic goes here
return Promise.resolve();
} › Setup notes
Install 'node-cron' and 'fancy-log' via npm. Run this process using a process manager like PM2 to ensure high availability and proper log capture.
import logging
from apscheduler.schedulers.blocking import BlockingScheduler
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def tri_hourly_job():
logger.info("Executing tri-hourly scheduled job")
try:
# Production logic goes here
pass
except Exception as e:
logger.error(f"Execution failed: {e}", exc_info=True)
if __name__ == '__main__':
scheduler = BlockingScheduler(timezone='UTC')
scheduler.add_job(tri_hourly_job, 'cron', hour='*/3', minute=0, id='tri_hourly_sync')
logger.info("Scheduler started. Running job every 3 hours.")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped.") › Setup notes
Install 'apscheduler' via pip. Run this script in a dedicated container or background service. The BlockingScheduler is ideal for single-purpose worker containers.
package main
import (
"log"
"time"
"github.com/robfig/cron/v3"
)
func main() {
// Initialize cron scheduler with UTC timezone
nyc, err := time.LoadLocation("UTC")
if err != nil {
log.Fatalf("Error loading UTC timezone: %v", err)
}
c := cron.New(cron.WithLocation(nyc))
_, err = c.AddFunc("0 */3 * * *", func() {
log.Println("Starting tri-hourly task execution...")
if err := executeTask(); err != nil {
log.Printf("Task execution failed: %v", err)
}
})
if err != nil {
log.Fatalf("Failed to schedule job: %v", err)
}
c.Start()
log.Println("Cron engine initialized")
select {} // Keep application alive
}
func executeTask() error {
// Production logic goes here
return nil
} › Setup notes
Use 'go get github.com/robfig/cron/v3' to fetch the library. Run this program as a daemon or systemd service to ensure continuous execution.
package com.example.scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TriHourlyScheduler {
private static final Logger logger = LoggerFactory.getLogger(TriHourlyScheduler.class);
// Spring cron format includes seconds: "0 0 */3 * * *" translates to every 3 hours
@Scheduled(cron = "0 0 */3 * * *", zone = "UTC")
public void executeTriHourlyTask() {
logger.info("Tri-hourly scheduled execution started.");
try {
runBusinessLogic();
logger.info("Tri-hourly scheduled execution completed successfully.");
} catch (Exception e) {
logger.error("Error during scheduled execution", e);
}
}
private void runBusinessLogic() {
// Production logic goes here
}
} › Setup notes
Ensure '@EnableScheduling' is declared on your main Spring Boot Application class. Spring requires a 6-field cron expression where the first field represents seconds.
apiVersion: batch/v1
kind: CronJob
metadata:
name: tri-hourly-sync-job
namespace: default
spec:
schedule: "0 */3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: worker
image: python:3.10-slim
command: ["python", "-c", "print('Running scheduled task')"]
restartPolicy: OnFailure › Setup notes
Apply this manifest using 'kubectl apply -f cronjob.yaml'. Setting 'concurrencyPolicy: Forbid' prevents a new job from starting if the previous one is still active.
Last verified:
Keep this cron job monitored 24/7
UptimeRobot alerts you the moment a scheduled job stops responding. Free plan monitors up to 50 endpoints — no credit card required.
Platform Equivalents
AWS EventBridge
Standard cron expressions often need conversion for AWS EventBridge schedules.
cron(0 */3 * * ? *) Systemd Timer
OnCalendar*-*-* 00/3:00:00
[Unit]
Description=Timer for cron expression: 0 */3 * * *
[Timer]
OnCalendar=*-*-* 00/3:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
At what exact times of the day does this cron schedule execute?
The job executes at midnight (00:00), 3:00 AM, 6:00 AM, 9:00 AM, 12:00 PM (noon), 3:00 PM, 6:00 PM, and 9:00 PM. All executions occur at the exact beginning of the hour (minute 0).
What happens to the 3-hour interval during Daylight Saving Time (DST) changes?
If your system runs on local time, spring-forward transitions can skip the 2:00 AM hour (meaning the next run is at 3:00 AM, causing a shorter interval), and autumn fall-backs can repeat the 1:00 AM hour, causing duplicate runs. Running your cron daemon in UTC completely eliminates this issue.
How can I prevent overlapping executions if a job takes longer than 3 hours?
You should use locking mechanisms. In Kubernetes, set concurrencyPolicy: Forbid. In Linux, wrap your script with the flock utility. In application code, implement distributed locks using Redis, Consul, or database-level advisory locks.
How can I offset this job to avoid high-concurrency resource spikes on the hour?
To avoid the 'thundering herd' problem, shift the minute field to a non-zero value, such as 15 */3 * * * (running at 15 minutes past the hour) or introduce a randomized sleep/jitter at the start of your script.
Is this expression compatible with AWS EventBridge or CloudWatch Events?
AWS EventBridge uses a 6-field cron format where the last field is the year and '?' is used for the day-of-week/day-of-month wildcard. Standard '0 */3 * * *' needs to be adapted to conform to AWS's specific syntax rules.
* Explore
Related expressions you might need
Last verified: