Execute Daily 4 AM Maintenance Tasks | CronBase
0 4 * * * Every day in the early morning at exactly four o'clock.
The `0 4 * * *` cron expression schedules a job to run once every day at exactly 4:00 AM. This daily cadence is highly popular in production environments for executing resource-intensive operations, such as database optimization, system backups, and log rotation, during off-peak hours when user activity is minimal.
- Minute
- 0
- Hour
- 4
- Day of Month
- *
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 7h 22m
- in 1d 7h
- in 2d 7h
- in 3d 7h
- in 4d 7h
* Tools
Code & Implementations
#!/usr/bin/env bash
# Ensure the script exits immediately if any command fails
set -euo pipefail
LOG_FILE="/var/log/daily_backup.log"
# Function to log messages with timestamps
log_message() {
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $1" >> "$LOG_FILE"
}
log_message "Starting daily maintenance task..."
# Implement jitter to avoid thundering herd issues
SLEEP_TIME=$((RANDOM % 300))
log_message "Sleeping for ${SLEEP_TIME} seconds to distribute load..."
sleep "$SLEEP_TIME"
# Execute the backup process
if pg_dump -U db_user -h localhost production_db > /backups/prod_$(date +%F).sql; then
log_message "Backup completed successfully."
else
log_message "ERROR: Backup process failed!"
exit 1
fi › Setup notes
Add this script to your crontab by running 'crontab -e' and appending the line: 0 4 * * * /path/to/script.sh >> /var/log/cron_output.log 2>&1
const cron = require('node-cron');
const { exec } = require('child_process');
console.log('Daily maintenance scheduler initialized.');
// Schedule task to run daily at 4:00 AM
cron.schedule('0 4 * * *', () => {
console.log(`[${new Date().toISOString()}] Initiating daily database cleanup...`);
exec('npm run db:cleanup', (error, stdout, stderr) => {
if (error) {
console.error(`Error during cleanup: ${error.message}`);
return;
}
if (stderr) {
console.warn(`Warnings during cleanup: ${stderr}`);
}
console.log(`Cleanup completed: ${stdout}`);
});
}, {
scheduled: true,
timezone: "Etc/UTC"
}); › Setup notes
Install the node-cron library using 'npm install node-cron' and run this script using a process manager like PM2 to ensure high availability.
import sys
import logging
from apt_pkg import init
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def daily_maintenance_job():
logger.info("Starting daily system cleanup and index optimization...")
try:
# Simulate work
logger.info("Optimization successfully completed.")
except Exception as e:
logger.error(f"Maintenance job failed: {str(e)}")
# In production, integrate alert mechanisms here
if __name__ == '__main__':
scheduler = BlockingScheduler()
# Schedule the job for daily at 4:00 AM UTC
scheduler.add_job(daily_maintenance_job, 'cron', hour=4, minute=0, timezone='UTC')
logger.info("Scheduler started. Task configured for 04:00 UTC daily.")
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped.")
sys.exit(0) › Setup notes
Install APScheduler via 'pip install apscheduler' and run this script as a persistent background daemon processes.
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/robfig/cron/v3"
)
func main() {
logger := log.New(os.Stdout, "CRON: ", log.LstdFlags|log.Lshortfile)
logger.Println("Initializing daily cron scheduler...")
// Use UTC timezone for predictable schedule execution
c := cron.New(cron.WithLocation(time.UTC))
_, err := c.AddFunc("0 4 * * *", func() {
logger.Println("Executing daily analytical aggregation...")
// Perform the actual work here
logger.Println("Analytical aggregation finished successfully.")
})
if err != nil {
logger.Fatalf("Error scheduling job: %v", err)
}
c.Start()
logger.Println("Scheduler started. Running daily at 04:00 UTC.")
// Keep the process alive until interrupted
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
logger.Println("Shutting down scheduler gracefully...")
c.Stop()
} › Setup notes
Run 'go get github.com/robfig/cron/v3' to fetch the dependency, then compile and run this application in your production environment.
package com.example.cron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
@Component
public class DailyMaintenanceScheduler {
private static final Logger logger = LoggerFactory.getLogger(DailyMaintenanceScheduler.class);
// Spring Cron uses 6 fields: second, minute, hour, day, month, day-of-week
@Scheduled(cron = "0 0 4 * * *", zone = "UTC")
public void runDailyMaintenance() {
logger.info("Daily maintenance task started at: {}", Instant.now());
try {
// Business logic for daily data pruning
pruneOldRecords();
logger.info("Daily maintenance task completed successfully.");
} catch (Exception ex) {
logger.error("Error during daily maintenance: ", ex);
}
}
private void pruneOldRecords() {
// Simulated database call
}
} › Setup notes
Ensure '@EnableScheduling' is declared on your Spring Boot main application class. The task will automatically execute daily at 4:00 AM UTC.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-cleanup-job
namespace: production
spec:
schedule: "0 4 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: database-cleaner
image: postgres:15-alpine
command:
- /bin/sh
- -c
- "psql -h db-service -U postgres -d app_prod -c 'VACUUM ANALYZE;'"
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
restartPolicy: OnFailure › Setup notes
Apply this manifest to your cluster using 'kubectl apply -f cronjob.yaml'. It schedules a daily cleanup job that forbids concurrent executions.
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 4 * * ? *) Systemd Timer
OnCalendar*-*-* 04:00:00
[Unit]
Description=Timer for cron expression: 0 4 * * *
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
How does Daylight Saving Time affect a 4:00 AM cron job?
Depending on your local timezone, a 4:00 AM job is usually safe from the 2:00 AM DST shift. However, if your system transitions timezone offsets, the local time of execution will shift relative to UTC. Running servers on UTC avoids this entirely.
What happens if a previous day's job is still running at 4:00 AM?
Standard cron daemons will launch a new instance of the job regardless of whether the previous one finished. To prevent overlapping executions, use a locking wrapper like 'flock' in Bash or application-level distributed locks.
How can I add jitter to avoid a thundering herd at 4:00 AM?
You can introduce a random sleep at the start of your execution script. For example, in Bash, running 'sleep $((RANDOM % 300))' will delay the actual task by up to 5 minutes, distributing the resource load across your cluster.
Can I run this job only on weekdays at 4:00 AM?
Yes, you can modify the expression to '0 4 * * 1-5'. This restricts the daily execution to Monday through Friday, which is ideal for business-centric processes that do not need to run over the weekend.
How do I capture and debug failures for a daily 4:00 AM task?
You should redirect both standard output and standard error to a dedicated log file, or forward them to a centralized logging system. Additionally, integrate an alerting tool (like PagerDuty or Slack webhooks) to notify your on-call team immediately if the job exits with a non-zero status.
* Explore
Related expressions you might need
Last verified: