Configure Every 45-Minute Cron Jobs | CronBase
*/45 * * * * At the start of every hour and forty-five minutes past every hour.
This cron expression triggers a job twice every hour, specifically at the top of the hour and forty-five minutes past the hour. Because standard cron resets step intervals at hour boundaries, this creates alternating execution gaps of forty-five and fifteen minutes, which is ideal for lightweight, non-continuous recurring tasks.
- Minute
- */45
- Hour
- *
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 21m 37s
- in 36m 37s
- in 1h 21m
- in 1h 36m
- in 2h 21m
* Tools
Code & Implementations
#!/usr/bin/env bash
# Production-ready wrapper for cron execution with file locking
set -euo pipefail
LOCKFILE="/var/run/my_45min_job.lock"
LOGFILE="/var/log/my_45min_job.log"
# Ensure single execution using flock to avoid overlapping runs
exec 200>"$LOCKFILE"
if ! flock -n 200; then
echo "[$(date -u)] Execution skipped: Job is already running." >> "$LOGFILE"
exit 0
fi
echo "[$(date -u)] Starting 45-minute interval task..." >> "$LOGFILE"
# Actual task execution
if /usr/local/bin/my-app-task >> "$LOGFILE" 2>&1; then
echo "[$(date -u)] Task completed successfully." >> "$LOGFILE"
else
echo "[$(date -u)] ERROR: Task failed with exit code $?" >> "$LOGFILE" >&2
exit 1
fi › Setup notes
Save this script to /usr/local/bin/run-task.sh, make it executable with 'chmod +x', and register it in your system crontab using 'crontab -e' with the line: */45 * * * * /usr/local/bin/run-task.sh
const cron = require('node-cron');
const { exec } = require('child_process');
let isRunning = false;
// Schedule task at minute 0 and 45 of every hour
cron.schedule('*/45 * * * *', async () => {
if (isRunning) {
console.warn(`[${new Date().toISOString()}] Warning: Previous execution still active. Skipping.`);
return;
}
isRunning = true;
console.log(`[${new Date().toISOString()}] Starting scheduled task...`);
try {
await runTask();
console.log(`[${new Date().toISOString()}] Task completed successfully.`);
} catch (error) {
console.error(`[${new Date().toISOString()}] Task failed:`, error);
} finally {
isRunning = false;
}
});
function runTask() {
return new Promise((resolve) => {
// Simulate processing work
setTimeout(() => {
resolve();
}, 5000);
});
} › Setup notes
Install node-cron using 'npm install node-cron', save this script as scheduler.js, and run it using 'node scheduler.js' in a background process manager like PM2.
import logging
import time
from apscheduler.schedulers.blocking import BlockingScheduler
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s'
)
logger = logging.getLogger(__name__)
def execute_job():
logger.info("Executing scheduled task (minute 0 or 45)...")
try:
# Perform actual work here
time.sleep(2) # Simulate work
logger.info("Task completed successfully.")
except Exception as e:
logger.error(f"Task failed: {str(e)}", exc_info=True)
if __name__ == "__main__":
scheduler = BlockingScheduler()
# */45 * * * * translates to minute="0,45"
scheduler.add_job(
execute_job,
'cron',
minute='0,45',
id='45_min_job',
coalesce=True,
max_instances=1
)
logger.info("Scheduler started. Running at minutes 0 and 45 of every hour.")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped cleanly.") › Setup notes
Install APScheduler using 'pip install APScheduler' and run this script using 'python scheduler.py'. It will run persistently in the foreground.
package main
import (
"context"
"log"
"sync"
"time"
"github.com/robfig/cron/v3"
)
type SafeJob struct {
mu sync.Mutex
}
func (j *SafeJob) Run() {
// Prevent concurrent execution if a run takes longer than 15 minutes
if !j.mu.TryLock() {
log.Println("Previous job is still running, skipping this execution.")
return
}
defer j.mu.Unlock()
log.Println("Starting scheduled task...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
if err := performTask(ctx); err != nil {
log.Printf("Error executing task: %v\n", err)
} else {
log.Println("Task completed successfully.")
}
}
func performTask(ctx context.Context) error {
select {
case <-time.After(2 * time.Second):
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
c := cron.New()
job := &SafeJob{}
_, err := c.AddJob("*/45 * * * *", job)
if err != nil {
log.Fatalf("Error scheduling job: %v", err)
}
c.Start()
log.Println("Cron scheduler started...")
select {} // Keep application running
} › Setup notes
Initialize a Go module, run 'go get github.com/robfig/cron/v3', save this code to main.go, and run it with 'go run main.go'.
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 IntervalTaskScheduler {
private static final Logger logger = LoggerFactory.getLogger(IntervalTaskScheduler.class);
// Spring scheduler handles '*/45 * * * *' by expanding it to '0,45' minutes
@Scheduled(cron = "0 0,45 * * * *")
public void executeTask() {
logger.info("Scheduled task execution started.");
try {
processBusinessLogic();
logger.info("Scheduled task executed successfully.");
} catch (Exception e) {
logger.error("An error occurred during task execution", e);
}
}
private void processBusinessLogic() throws InterruptedException {
// Simulate processing workload
Thread.sleep(5000);
}
} › Setup notes
Ensure your Spring Boot application is annotated with @EnableScheduling. Place this class in your component-scanned package, and Spring will automatically run it.
apiVersion: batch/v1
kind: CronJob
metadata:
name: interval-cleanup-job
namespace: default
spec:
schedule: "*/45 * * * *"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 300
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: worker
image: busybox:1.36
command:
- /bin/sh
- -c
- "echo 'Starting cleanup task...'; sleep 10; echo 'Task complete.'"
restartPolicy: OnFailure › Setup notes
Save this YAML configuration to a file named 'cronjob.yaml' and apply it to your Kubernetes cluster using the command: kubectl apply -f cronjob.yaml
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(*/45 * * * ? *) Systemd Timer
OnCalendar*-*-* *:00/45:00
[Unit]
Description=Timer for cron expression: */45 * * * *
[Timer]
OnCalendar=*-*-* *:00/45:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
Why does this schedule run twice an hour instead of every 45 minutes continuously?
Standard cron evaluates fields independently. The expression `*/45` translates to "every 45th minute starting from 0 within the current hour," matching only minute 0 and 45. The interval resets at the top of the next hour, creating a 15-minute gap.
How can I achieve a true rolling 45-minute execution interval?
To run exactly every 45 minutes without hour-boundary resets, you should avoid standard cron. Instead, use an application-level scheduler like Celery, Hangfire, or Go's ticker, or run a continuous background daemon with a sleep/delay loop.
What happens if my job takes longer than 15 minutes to complete?
If a job started at minute 45 runs longer than 15 minutes, it will overlap with the next execution at minute 0. You must implement locking mechanisms (like flock in Bash or redis-locks in Node) or set concurrency policies to prevent concurrent runs.
How do daylight saving time (DST) shifts affect this 45-minute schedule?
During a DST shift, your system clock may jump forward or backward. Since this schedule runs relative to the wall clock (at minute 0 and 45), a shift will cause one interval to be skipped or repeated. Run your cron daemon in UTC to avoid this.
Can I restrict this 45-minute cadence to only run during business hours?
Yes, you can modify the hour field. For example, `*/45 9-17 * * 1-5` will restrict the executions to minute 0 and 45 of every hour between 9:00 AM and 5:45 PM, Monday through Friday.
* Explore
Related expressions you might need
Last verified: