Run Daily 3 AM Database Backups | CronBase
0 3 * * * Every single day in the middle of the night at exactly three o'clock in the morning.
The `0 3 * * *` cron expression schedules a task to run daily at exactly 3:00 AM. This off-peak timing is ideal for resource-intensive operations like database backups, log rotation, data warehousing ETL syncs, and system updates, ensuring minimal performance impact on active daytime users.
- Minute
- 0
- Hour
- 3
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 6h 21m
- in 1d 6h
- in 2d 6h
- in 3d 6h
- in 4d 6h
* Tools
Code & Implementations
#!/usr/bin/env bash
# Crontab entry: 0 3 * * * /usr/local/bin/daily_backup.sh
set -euo pipefail
LOCKFILE="/var/tmp/daily_backup.lock"
# Prevent concurrent execution of the daily 3 AM backup
exec 9>"$LOCKFILE"
if ! flock -n 9; then
echo "Error: Another backup process is already running." >&2
exit 1
fi
echo "Starting daily maintenance at $(date)"
# Perform backup operations here
/usr/local/bin/backup_db.sh --output /mnt/backups/daily/
echo "Daily maintenance completed successfully." › Setup notes
Place this script in /usr/local/bin/daily_backup.sh, make it executable with chmod +x, and add 0 3 * * * /usr/local/bin/daily_backup.sh to your system crontab.
const cron = require('node-cron');
const { exec } = require('child_process');
// Schedule task to run daily at 3:00 AM UTC to avoid DST anomalies
cron.schedule('0 3 * * *', () => {
console.log(`[${new Date().toISOString()}] Initiating daily 3 AM database cleanup...`);
exec('/usr/local/bin/cleanup-logs.sh', (error, stdout, stderr) => {
if (error) {
console.error(`Execution error: ${error.message}`);
return;
}
if (stderr) {
console.warn(`Stderr: ${stderr}`);
}
console.log(`Stdout: ${stdout}`);
console.log(`[${new Date().toISOString()}] Daily cleanup finished successfully.`);
});
}, {
scheduled: true,
timezone: "UTC"
}); › Setup notes
Install node-cron via npm, then run this script as a daemon process using a process manager like PM2 to guarantee constant execution.
import logging
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("daily_scheduler")
def run_daily_task():
logger.info("Starting daily 3 AM maintenance task at %s", datetime.utcnow())
try:
# Business logic goes here
pass
except Exception as e:
logger.error("Daily task failed: %s", str(e), exc_info=True)
if __name__ == "__main__":
scheduler = BlockingScheduler(timezone="UTC")
# 0 3 * * * translates to hour=3, minute=0 daily
scheduler.add_job(run_daily_task, 'cron', hour=3, minute=0)
logger.info("Scheduler started. Running daily task at 3:00 AM UTC.")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped.") › Setup notes
Install APScheduler using pip install apscheduler and execute this python script within a systemd service wrapper.
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/robfig/cron/v3"
)
func main() {
// Use UTC timezone to prevent DST anomalies at 3 AM
nyc, err := time.LoadLocation("UTC")
if err != nil {
log.Fatalf("Failed to load timezone: %v", err)
}
c := cron.New(cron.WithLocation(nyc))
// 0 3 * * * represents daily at 3:00 AM
_, err = c.AddFunc("0 3 * * *", func() {
log.Println("Daily 3:00 AM cron job started.")
executeBackup()
})
if err != nil {
log.Fatalf("Error scheduling cron job: %v", err)
}
c.Start()
log.Println("Cron scheduler initialized for 3 AM daily run.")
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
c.Stop()
}
func executeBackup() {
// Implementation of daily database or log maintenance
log.Println("Backup complete.")
} › Setup notes
Initialize a Go module, run go get github.com/robfig/cron/v3, and run the compiled binary as a background service.
package com.cronbase.scheduler;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.logging.Logger;
@Component
public class DailyMaintenanceScheduler {
private static final Logger LOGGER = Logger.getLogger(DailyMaintenanceScheduler.class.getName());
// Spring cron format: "second minute hour day-of-month month day-of-week"
@Scheduled(cron = "0 0 3 * * *", zone = "UTC")
public void executeDailyTask() {
LOGGER.info("Starting daily maintenance routine at " + Instant.now());
try {
performDatabaseCleanup();
LOGGER.info("Daily maintenance completed successfully.");
} catch (Exception e) {
LOGGER.severe("Failed to execute daily maintenance: " + e.getMessage());
}
}
private void performDatabaseCleanup() {
// Business logic here
}
} › Setup notes
Annotate your main application class with @EnableScheduling and ensure this component is scanned by Spring Context.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup-3am
namespace: infrastructure
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: database-exporter
image: postgres:15-alpine
command:
- /bin/sh
- -c
- "pg_dump -h db.prod -U postgres prod_db | gzip > /mnt/backups/db-$(date +%F).sql.gz"
volumeMounts:
- name: backup-volume
mountPath: /mnt/backups
restartPolicy: OnFailure
volumes:
- name: backup-volume
persistentVolumeClaim:
claimName: backup-pvc › Setup notes
Apply this configuration to your cluster using kubectl apply -f cronjob.yaml after verifying that the persistent volume claim exists.
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*-*-* 03:00:00
[Unit]
Description=Timer for cron expression: 0 3 * * *
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
How does Daylight Saving Time affect a 3:00 AM cron schedule?
Depending on your local timezone settings, the transition into Daylight Saving Time can cause the 3:00 AM job to run twice or skip entirely. Running your servers on UTC is the industry best practice to prevent this issue.
What happens if a previous day's 3:00 AM run is still executing when the next one starts?
Standard cron daemons will launch a concurrent process, which can lead to database deadlocks or resource starvation. You should implement locking mechanisms like 'flock' in Bash or distributed locks in application code to prevent overlapping.
How can I stagger multiple jobs scheduled at 3:00 AM to prevent resource spikes?
Introduce a randomized delay or sleep interval at the start of your scripts. For example, prepending 'sleep $((RANDOM % 300))' in a Bash task staggers execution across a five-minute window.
How should I monitor this off-hours job to ensure it actually ran?
Do not rely solely on push notifications. Use a 'dead-man's switch' monitoring service (like Healthchecks.io or Opsgenie) that alerts you if a ping is not received by 3:15 AM.
Can I restrict this daily 3:00 AM run to only execute on weekdays?
Yes, you can modify the expression to '0 3 * * 1-5' to target Monday through Friday, or '0 3 * * 1,2,3,4,5' depending on your specific cron dialect's syntax support.
* Explore
Related expressions you might need
Last verified: