Run Every 12 Hours Cron Schedule | CronBase
0 */12 * * * Twice daily at midnight and noon
The `0 */12 * * *` cron expression schedules a task to run twice daily, specifically at midnight (12:00 AM) and noon (12:00 PM). This twelve-hour interval is ideal for medium-frequency maintenance tasks, database backups, and data synchronization processes that do not require real-time execution but must run regularly.
- Minute
- 0
- Hour
- */12
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 3h 20m
- in 15h 20m
- in 1d 3h
- in 1d 15h
- in 2d 3h
* Tools
Code & Implementations
#!/usr/bin/env bash
# System cron job implementation for twice-daily database backup
# Typically installed in /etc/cron.d/db-backup or via crontab -e
set -euo pipefail
BACKUP_DIR="/var/backups/postgres"
LOG_FILE="/var/log/db-backup.log"
# Ensure backup directory exists
mkdir -p "${BACKUP_DIR}"
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] Starting semi-daily database backup..." >> "${LOG_FILE}"
# Execute backup with error handling
if pg_dump -U postgres prod_db | gzip > "${BACKUP_DIR}/db_backup_$(date +%Y%m%d_%H%M%S).sql.gz"; then
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] Backup completed successfully." >> "${LOG_FILE}"
else
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] ERROR: Database backup failed!" >&2
# Send alert to monitoring system here (e.g., PagerDuty or curl webhook)
exit 1
fi › Setup notes
Save this script to /usr/local/bin/db-backup.sh, make it executable, and add '0 */12 * * * /usr/local/bin/db-backup.sh' to your system crontab.
const cron = require('node-cron');
const { exec } = require('child_process');
// Schedule task to run twice daily at midnight and noon (0 */12 * * *)
const schedule = '0 */12 * * *';
const job = cron.schedule(schedule, () => {
console.log(`[${new Date().toISOString()}] Initiating 12-hour cache invalidation and data sync...`);
exec('npm run sync-cache', (error, stdout, stderr) => {
if (error) {
console.error(`[${new Date().toISOString()}] Sync failed:`, error.message);
// Implement alerting/notification logic here
return;
}
if (stderr) {
console.warn(`[${new Date().toISOString()}] Sync warning:`, stderr);
}
console.log(`[${new Date().toISOString()}] Sync completed:`, stdout.trim());
});
}, {
scheduled: true,
timezone: "UTC"
});
job.start(); › Setup notes
Install the dependency using 'npm install node-cron' and run this script as a persistent background process using PM2 or systemd.
import logging
import sys
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[logging.StreamHandler(sys.stdout)]
)
def execute_semi_daily_cleanup():
logging.info("Starting 12-hour temporary file cleanup process...")
try:
# Business logic simulation
# perform_cleanup()
logging.info("Temporary file cleanup completed successfully.")
except Exception as e:
logging.error(f"Cleanup failed: {str(e)}", exc_info=True)
# Trigger alert notifications here
if __name__ == "__main__":
scheduler = BlockingScheduler()
# 0 */12 * * * mapped to CronTrigger (minute=0, hour='*/12')
trigger = CronTrigger(minute=0, hour='*/12', timezone='UTC')
scheduler.add_job(
execute_semi_daily_cleanup,
trigger=trigger,
id='semi_daily_cleanup_job',
replace_existing=True
)
logging.info("Scheduler started. Job configured for twice-daily execution (0 */12 * * *).")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logging.info("Scheduler stopped cleanly.") › Setup notes
Install APScheduler via 'pip install apscheduler' and run this script as a daemonized service within your environment.
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/robfig/cron/v3"
)
func runSemiDailySync() {
log.Printf("[%s] Starting 12-hour data pipeline synchronization...", time.Now().UTC().Format(time.RFC3339))
// Simulate processing
time.Sleep(5 * time.Second)
log.Printf("[%s] Data pipeline synchronization complete.", time.Now().UTC().Format(time.RFC3339))
}
func main() {
// Use UTC timezone to prevent DST shift anomalies
c := cron.New(cron.WithLocation(time.UTC))
// Standard cron: 0 */12 * * *
_, err := c.AddFunc("0 */12 * * *", runSemiDailySync)
if err != nil {
log.Fatalf("Failed to schedule cron job: %v", err)
}
c.Start()
log.Println("Cron scheduler started. Running twice-daily tasks (0 */12 * * *)...")
// Keep process alive until interrupted
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
log.Println("Shutting down scheduler gracefully...")
c.Stop()
} › Setup notes
Run 'go get github.com/robfig/cron/v3' to fetch the library, compile the binary using 'go build', and run it as a system service.
package com.example.cron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class SemiDailyMaintenanceTask {
private static final Logger log = LoggerFactory.getLogger(SemiDailyMaintenanceTask.class);
// standard cron: 0 */12 * * * (Spring uses standard 6-field/5-field macro or standard cron string)
// In Spring, "0 0 */12 * * *" represents second=0, minute=0, hour=every 12th hour.
@Scheduled(cron = "0 0 */12 * * *", zone = "UTC")
public void executeMaintenance() {
log.info("Starting twice-daily database index optimization...");
try {
// Business logic goes here
// indexService.rebuildIndexes();
log.info("Database index optimization completed successfully.");
} catch (Exception e) {
log.error("Critical failure during semi-daily maintenance: ", e);
// Invoke alert system / dead man's switch notification
}
}
} › Setup notes
Enable scheduling in your Spring Boot application by adding '@EnableScheduling' to your main configuration class.
apiVersion: batch/v1
kind: CronJob
metadata:
name: database-vacuum-job
namespace: infrastructure
spec:
schedule: "0 */12 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: postgres-vacuum
image: postgres:15-alpine
command:
- /bin/sh
- -c
- |
echo "Starting database vacuum process..."
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "VACUUM ANALYZE;"
env:
- name: DB_HOST
value: "postgres-service.database.svc.cluster.local"
- name: DB_USER
value: "postgres"
- name: DB_NAME
value: "production"
restartPolicy: OnFailure › Setup notes
Apply this manifest to your cluster using 'kubectl apply -f cronjob.yaml' inside the designated namespace.
Last verified:
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.
cron(0 */12 * * ? *) Systemd Timer
OnCalendar*-*-* 00/12:00:00
[Unit]
Description=Timer for cron expression: 0 */12 * * *
[Timer]
OnCalendar=*-*-* 00/12:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
How does the 12-hour cron schedule react to Daylight Saving Time changes?
If your system timezone is set to local time, DST transitions can cause the job to run 11 or 13 hours apart, or skip/double-execute. To avoid this, always configure your cron daemon or scheduler to run in the UTC timezone, which does not observe DST.
Can I offset the execution time to avoid resource spikes at midnight and noon?
Yes. If you want to run every 12 hours but avoid the top of the hour, change the minute field. For example, `30 */12 * * *` will run at 12:30 AM and 12:30 PM, spreading the load away from other system processes starting on the hour.
What is the best way to monitor a job that only runs twice a day?
Passive monitoring (log parsing) is insufficient for twice-daily tasks. Use active push-based monitoring ('Dead Man's Switch') like Healthchecks.io. If the monitoring endpoint does not receive a ping within 12 hours plus a small grace buffer, it immediately triggers an alert.
How do I prevent a long-running 12-hour job from overlapping with its next run?
Use lock mechanisms or concurrency policies. In Kubernetes, set `concurrencyPolicy: Forbid`. In Linux bash scripts, wrap your execution using the `flock` utility (e.g., `flock -n /var/lock/myjob.lock mycommand`) to prevent concurrent execution if a previous run hangs.
Does `*/12` always run at exactly 00:00 and 12:00?
Yes, in standard cron implementations, the step value `*/12` divides the 24-hour day starting from 0. This results in executions at hour 0 (midnight) and hour 12 (noon). If you want specific hours like 6 AM and 6 PM, use explicit list notation: `0 6,18 * * *`.
* Explore
Related expressions you might need
Last verified: