Run Weekly Backups on Mondays at 2 AM | CronBase
0 2 * * 1 Every Monday morning at two o'clock.
This cron expression schedules a task to run once a week on Mondays at exactly 2:00 AM. It is widely used in production environments for executing resource-intensive weekly maintenance tasks, such as database vacuuming, log archiving, SSL certificate renewals, and system backups, during low-traffic periods.
- Minute
- 0
- Hour
- 2
- Day of Month
- *
- Month
- *
- Day of Week
- 1
Next 5 Runs
- in 1d 5h
- in 8d 5h
- in 15d 5h
- in 22d 5h
- in 29d 5h
* Tools
Code & Implementations
#!/usr/bin/env bash
set -euo pipefail
# Define lock file to prevent concurrent executions
LOCKFILE="/var/lock/weekly-maintenance.lock"
# Execute weekly task with flock to ensure exclusive execution
exec 9>"$LOCKFILE"
if flock -n 9; then
echo "[$(date -u)] Starting weekly maintenance task..."
# Insert production commands here
# Example: /usr/local/bin/backup-db.sh
echo "[$(date -u)] Task completed successfully."
else
echo "[$(date -u)] Error: Task is already running!"
exit 1
fi › Setup notes
Add the entry to your system crontab by running 'crontab -e' and appending: 0 2 * * 1 /usr/local/bin/weekly-maintenance.sh >> /var/log/cron-weekly.log 2>&1
const cron = require('node-cron');
const { exec } = require('child_process');
// Schedule task to run at 2:00 AM every Monday
cron.schedule('0 2 * * 1', () => {
console.log(`[${new Date().toISOString()}] Initiating weekly cleanup...`);
exec('/usr/local/bin/cleanup-script.sh', (error, stdout, stderr) => {
if (error) {
console.error(`Execution error: ${error.message}`);
return;
}
if (stderr) {
console.warn(`Execution warning: ${stderr}`);
}
console.log(`Execution success: ${stdout}`);
});
}, {
scheduled: true,
timezone: "UTC"
}); › Setup notes
Install node-cron using 'npm install node-cron' and run this script using node. Ensure your process manager (like PM2) keeps the process alive.
import logging
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('weekly_scheduler')
def run_weekly_job():
logger.info(f"Starting weekly job at {datetime.utcnow()} UTC")
try:
# Place production workload here
pass
except Exception as e:
logger.error(f"Job failed: {str(e)}")
scheduler = BlockingScheduler(timezone='UTC')
# '1' represents Monday in APScheduler cron format
scheduler.add_job(run_weekly_job, 'cron', day_of_week='mon', hour=2, minute=0)
try:
logger.info("Starting scheduler...")
scheduler.start()
except (KeyboardInterrupt, SystemExit):
logger.info("Scheduler stopped.") › Setup notes
Install APScheduler using 'pip install apscheduler' and run the script. Ensure systemd or supervisor keeps the script running in the background.
package main
import (
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/robfig/cron/v3"
)
func main() {
// Use UTC timezone to avoid DST issues
nyc, err := time.LoadLocation("UTC")
if err != nil {
log.Fatalf("Failed to load timezone: %v", err)
}
c := cron.New(cron.WithLocation(nyc))
_, err = c.AddFunc("0 2 * * 1", func() {
log.Println("Weekly Monday job started...")
// Implement your logic here
})
if err != nil {
log.Fatalf("Error scheduling job: %v", err)
}
c.Start()
log.Println("Cron engine started. Waiting for Monday 2:00 AM UTC...")
// Keep application running until interrupted
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
c.Stop()
} › Setup notes
Initialize a Go module, run 'go get github.com/robfig/cron/v3', and execute the program with 'go run main.go'.
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.logging.Logger;
@Component
public class WeeklyMaintenanceScheduler {
private static final Logger LOGGER = Logger.getLogger(WeeklyMaintenanceScheduler.class.getName());
// Standard Spring Cron format: second, minute, hour, day of month, month, day of week
@Scheduled(cron = "0 0 2 * * MON", zone = "UTC")
public void executeWeeklyTask() {
LOGGER.info("Weekly Monday maintenance started at " + Instant.now());
try {
// Perform database optimization or log rotation
} catch (Exception e) {
LOGGER.severe("Weekly maintenance failed: " + e.getMessage());
}
}
} › Setup notes
Ensure your Spring Boot application class is annotated with @EnableScheduling. Spring will automatically detect and register this scheduled bean.
apiVersion: batch/v1
kind: CronJob
metadata:
name: weekly-database-cleanup
namespace: production
spec:
schedule: "0 2 * * 1"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: database-cleaner
image: postgres:15-alpine
command:
- /bin/sh
- -c
- "vacuumdb -U postgres -d production_db -z -v"
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
restartPolicy: OnFailure › Setup notes
Apply the manifest to your cluster using 'kubectl apply -f cronjob.yaml'. Ensure your cluster timezone is set correctly or configure UTC explicitly.
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 2 ? * 1 *) Systemd Timer
OnCalendarMon *-*-* 02:00:00
[Unit]
Description=Timer for cron expression: 0 2 * * 1
[Timer]
OnCalendar=Mon *-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
How does Daylight Saving Time (DST) affect a job scheduled at 2:00 AM?
During DST transitions, 2:00 AM might occur twice (autumn) or not at all (spring). To prevent skipped or duplicate executions, run your system clock and cron daemon in UTC, which does not observe DST.
What happens if the server is powered off at Monday 2:00 AM?
Standard cron will not run missed jobs retroactively when the server boots back up. If you need guaranteed execution of missed tasks, consider using anacron or a systemd timer with Persistent=true.
Is Monday at 2:00 AM a safe time to run heavy database migrations?
While traffic is generally low, running migrations right before the business week starts is risky. If the migration fails or locks tables, it may disrupt Monday morning business. Consider scheduling migrations for Saturday night instead.
How can I prevent multiple instances of this weekly job from overlapping?
Use a locking utility like flock in Bash, or a distributed lock manager (like Redis/Redlock) if running in a clustered environment, to ensure only one instance of the job executes at a time.
How do I test this cron expression locally before deploying it?
You can use online parser tools to verify the schedule, or simulate it locally by setting your system time to Sunday 1:59 AM in a containerized environment to watch the execution trigger at 2:00 AM.
* Explore
Related expressions you might need
Last verified: