Web Development

What Are Common Cron Job Patterns for Backups and Maintenance?

Learn the most useful cron patterns for common tasks like backups, database maintenance, log rotation, and cleanup jobs with real-world examples.

By Inventive HQ Team

The most common cron patterns for backups and maintenance stagger jobs into daily, weekly, and monthly tiers scheduled during off-peak hours (typically 1–4 AM), so cheap tasks run often and expensive tasks run rarely — without any two jobs competing for the same disk or CPU at once. A typical production schedule looks like 0 2 * * * for a nightly incremental backup, 0 3 * * 0 for a weekly full backup and database optimization pass on Sunday, 0 4 1 * * for a monthly archive or cleanup job, and 0 * * * * for hourly log-size or health checks — each offset by 15–60 minutes from its neighbors so nothing overlaps.

That's the pattern in one sentence. The rest of this guide walks through the proven schedules for backups, database maintenance, log rotation, cache clearing, certificate renewal, and monitoring — with the actual scripts, the reasoning behind each timing choice, and the mistakes (overlapping jobs, no lock files, no retention policy) that turn a "set it and forget it" cron job into a 3 AM page.

Loading interactive tool...

When maintenance jobs typically fire

Most backup and maintenance schedules cluster around the same handful of hours because that's when production traffic is lowest and I/O contention is cheapest. The diagram below shows a typical 24-hour maintenance schedule, staggered so daily, weekly, and monthly jobs never collide:

A 24-hour maintenance schedule on a clock face A 24-hour clock face showing staggered maintenance jobs: hourly log checks, a 1 AM config sync, a 2 AM daily backup, a 3 AM weekly database optimization, and a 4 AM monthly cleanup, with a marker sweeping around the clock to show the order jobs fire in. A typical staggered maintenance schedule (24-hour clock) 0:00 6:00 12:00 18:00 hourly log check 1am config sync 2–3am backup / DB optimize 4am cleanup

Reference: cron patterns covered in this guide

ScheduleCron expressionTypical use case
Every hour, on the hour0 * * * *Log size checks, health checks, cache clearing
Daily at 1 AM0 1 * * *Config sync, log cleanup
Daily at 2 AM0 2 * * *Incremental/nightly backup
Four times daily0 2,8,14,20 * * *High-frequency backup for critical systems
Daily at midnight0 0 * * *Log rotation, stats collection
Weekdays only at 2 AM0 2 * * 1-6Incremental backup (paired with a Sunday full backup)
Weekly, Sunday at 2–4 AM0 2 * * 0 / 0 3 * * 0 / 0 4 * * 0Full backup, database optimize/vacuum, integrity check
Twice daily (3 AM / 3 PM)0 3 * * * and 0 15 * * *SSL certificate renewal check (certbot)
Monthly, 1st at 4 AM0 4 1 * *Archive compaction, deep cleanup, monthly reporting

Common Cron Patterns for System Administration

Cron is most commonly used for automation of routine maintenance and backup tasks. Understanding common patterns helps you implement reliable automated systems.

Daily Backups

Daily Backup at 2 AM

0 2 * * * /backup/scripts/daily-backup.sh

This runs every day at 2 AM, a common time when systems have low traffic.

Backup Script Example:

#!/bin/bash
BACKUP_DIR="/backups/daily"
DATE=$(date +%Y%m%d)
DB_FILE="$BACKUP_DIR/database-$DATE.sql"

# Create directory if needed
mkdir -p "$BACKUP_DIR"

# Backup database
mysqldump -u backup_user -p'password' --all-databases > "$DB_FILE"

# Compress backup
gzip "$DB_FILE"

# Delete backups older than 30 days
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete

echo "Backup completed: $DB_FILE.gz" | mail -s "Backup Report" admin@example.com

Multiple Backups per Day

For critical systems, backup more frequently:

0 2,8,14,20 * * * /backup/scripts/daily-backup.sh

This runs 4 times daily (2 AM, 8 AM, 2 PM, 8 PM).

Incremental Backups

Run full backups weekly, incremental daily:

# Full backup every Sunday at 2 AM
0 2 * * 0 /backup/scripts/full-backup.sh

# Incremental backup daily at 2 AM, except Sunday
0 2 * * 1-6 /backup/scripts/incremental-backup.sh

Database Maintenance

Optimize Database Weekly

0 3 * * 0 mysqladmin -u admin -p'password' optimize

Runs every Sunday at 3 AM to optimize all databases.

Database Integrity Check

0 4 * * 0 mysqlcheck -u admin -p'password' --all-databases --check-only | mail -s "Database Check Report" admin@example.com

Checks database integrity every Sunday at 4 AM and emails results.

Vacuum PostgreSQL Database

0 2 * * 0 vacuumdb -U postgres -d mydb

Reclaims storage in PostgreSQL every Sunday at 2 AM.

Log Rotation and Cleanup

Daily Log Cleanup

0 1 * * * /log-cleanup/scripts/cleanup.sh

Log Cleanup Script:

#!/bin/bash
LOG_DIR="/var/log/app"

# Delete logs older than 90 days
find "$LOG_DIR" -name "*.log" -mtime +90 -delete

# Compress logs older than 7 days
find "$LOG_DIR" -name "*.log" -mtime +7 -exec gzip {} \;

# Keep compressed logs for 180 days
find "$LOG_DIR" -name "*.log.gz" -mtime +180 -delete
Advertisement

Hourly Log Size Check

0 * * * * /log-cleanup/scripts/check-size.sh

Prevents logs from consuming too much disk space by running hourly.

Rotate Logs Daily

0 0 * * * logrotate /etc/logrotate.conf

Runs daily at midnight to rotate logs based on logrotate configuration.

Cache Clearing

Clear Cache Hourly

0 * * * * /cache/scripts/clear-cache.sh

Cache Clearing Script:

#!/bin/bash
CACHE_DIR="/var/cache/app"

# Clear temporary cache files
rm -f "$CACHE_DIR"/*.tmp
rm -rf "$CACHE_DIR"/sessions/*

# Restart cache service if needed
systemctl restart memcached

echo "Cache cleared at $(date)" >> /var/log/cache-clear.log

Clear Old Cache Files Weekly

0 2 * * 0 find /var/cache/app -type f -mtime +7 -delete

Deletes cache files not accessed in 7 days, every Sunday at 2 AM.

File Cleanup and Archival

Archive Old Files

0 3 * * * /archive/scripts/archive-old-files.sh

Archive Script:

#!/bin/bash
SOURCE_DIR="/data/uploads"
ARCHIVE_DIR="/data/archive"
DAYS=180

# Find files older than 180 days
find "$SOURCE_DIR" -type f -mtime +"$DAYS" | while read file; do
  # Archive to dated subdirectory
  YEAR=$(stat -c %y "$file" | cut -d- -f1)
  mkdir -p "$ARCHIVE_DIR/$YEAR"
  mv "$file" "$ARCHIVE_DIR/$YEAR/"
done

# Compress archives monthly
find "$ARCHIVE_DIR" -type f -mtime +30 -exec gzip {} \;

Delete Temporary Files

0 4 * * * find /tmp -type f -mtime +7 -delete
find /var/tmp -type f -mtime +14 -delete

Cleans up temporary files older than a week (or two weeks for /var/tmp).

Monthly Deep Cleanup

Reserve the most expensive maintenance work — the kind that's wasteful to run daily or even weekly — for a fixed date once a month:

0 4 1 * * /archive/scripts/monthly-cleanup.sh

This fires at 4 AM on the 1st of every month: 0 minute, 4 hour, 1 day-of-month, * every month, * every day-of-week. Typical monthly-tier jobs include compacting archive directories, purging soft-deleted records past their retention window, rotating long-lived audit logs, and running a full security or vulnerability sweep. Because day-of-month and day-of-week are evaluated as an OR (not an AND) when both are restricted, keep day-of-week as * here — otherwise the job would fire on either the 1st or every matching weekday, not just "the 1st if it's also that weekday."

Certificate Management

Renew SSL Certificates

0 3 * * * /opt/letsencrypt/certbot renew --quiet && systemctl reload nginx

Checks for certificates needing renewal daily at 3 AM and reloads nginx if certificates are updated.

For Let's Encrypt with certbot, running twice daily provides redundancy:

0 3 * * * /opt/letsencrypt/certbot renew --quiet
0 15 * * * /opt/letsencrypt/certbot renew --quiet

Configuration File Syncing

Sync Configuration Daily

0 1 * * * /scripts/sync-config.sh

Sync Script:

#!/bin/bash
# Backup current config
cp -r /etc/app /backups/config-$(date +%Y%m%d).bak

# Sync from central repository
git -C /etc/app pull origin main

# Restart service if config changed
if ! diff -q /backups/config-$(date +%Y%m%d).bak /etc/app > /dev/null; then
  systemctl restart app
  echo "Config updated and service restarted" | mail -s "Config Update" admin@example.com
fi

Security Scanning

Run Security Scans Weekly

0 2 * * 0 /security/scripts/vulnerability-scan.sh

Security Scan Script:

#!/bin/bash
# Run security scanner
trivy image --exit-code 0 myapp:latest > /reports/security-scan-$(date +%Y%m%d).txt

# Email report if vulnerabilities found
if grep -q "vulnerability" /reports/security-scan-$(date +%Y%m%d).txt; then
  mail -s "Security Vulnerabilities Found" admin@example.com < /reports/security-scan-$(date +%Y%m%d).txt
fi

Update Security Patches

0 1 * * * apt-get update && apt-get upgrade -y

Checks for and installs security updates daily at 1 AM.

Monitoring and Health Checks

Check System Health Hourly

0 * * * * /monitoring/scripts/health-check.sh

Health Check Script:

#!/bin/bash
THRESHOLD=80

# Check disk usage
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')

if [ "$DISK_USAGE" -gt "$THRESHOLD" ]; then
  echo "Disk usage at ${DISK_USAGE}%" | mail -s "Disk Space Alert" admin@example.com
fi

# Check memory
FREE_MEM=$(free | awk 'NR==2 {print int($3/$2 * 100)}')

if [ "$FREE_MEM" -gt 80 ]; then
  echo "Memory usage at ${FREE_MEM}%" | mail -s "Memory Alert" admin@example.com
fi

Database Connection Test

0 * * * * /monitoring/scripts/db-connection-test.sh

Tests database connectivity every hour and alerts if connection fails.

Data Synchronization

Sync Data to Remote Server

0 22 * * * rsync -avz /data/important/ user@backup-server:/backups/data/

Syncs important data to a backup server every day at 10 PM.

Report Generation

Generate Daily Reports

0 6 * * * /reports/scripts/generate-daily-report.sh

Generates reports and emails them before business hours.

Report Generation Script:

#!/bin/bash
REPORT_DIR="/reports/$(date +%Y/%m)"
mkdir -p "$REPORT_DIR"

# Generate various reports
/reports/scripts/user-activity-report.sh > "$REPORT_DIR/users-$(date +%Y%m%d).txt"
/reports/scripts/system-status-report.sh > "$REPORT_DIR/status-$(date +%Y%m%d).txt"
/reports/scripts/error-report.sh > "$REPORT_DIR/errors-$(date +%Y%m%d).txt"

# Email report
tar czf "$REPORT_DIR.tar.gz" "$REPORT_DIR"
mail -s "Daily Reports" admin@example.com -a "$REPORT_DIR.tar.gz"

Statistics and Reporting

Collect Statistics

0 0 * * * /scripts/collect-stats.sh

Stats Collection Script:

#!/bin/bash
STATS_DB="/var/stats/stats.db"

# Collect various metrics
TIMESTAMP=$(date +%s)
UPTIME=$(cat /proc/uptime | awk '{print int($1)}')
LOAD=$(cat /proc/loadavg | awk '{print $1}')
CPU_USAGE=$(top -bn1 | grep Cpu | awk '{print 100-$8}')
MEM_USAGE=$(free | awk 'NR==2 {print $3/$2*100}')

# Store in database
sqlite3 "$STATS_DB" "INSERT INTO metrics VALUES ($TIMESTAMP, $UPTIME, $LOAD, $CPU_USAGE, $MEM_USAGE)"

Best Practices for Maintenance Cron Jobs

  1. Always log output:
0 2 * * * /backup/scripts/daily-backup.sh >> /var/log/backup.log 2>&1
  1. Use lock files to prevent concurrent execution:
LOCK_FILE="/tmp/backup.lock"
if [ -f "$LOCK_FILE" ]; then
  echo "Backup already running"
  exit 1
fi
touch "$LOCK_FILE"
# do work
rm "$LOCK_FILE"
  1. Monitor cron job success/failure:
0 6 * * * /monitoring/scripts/check-cron-success.sh
  1. Schedule during low-traffic periods: 2-4 AM is typical

  2. Stagger multiple jobs to avoid overwhelming the system

  3. Document the purpose of each cron job with comments

  4. Test scripts manually before scheduling

  5. Monitor disk space for backups and logs

  6. Implement retention policies for old backups and logs

  7. Set appropriate permissions on cron scripts and output files

Common cron patterns make system administration much simpler. By using these proven patterns, you establish reliable automated systems that keep your infrastructure running smoothly.

Frequently Asked Questions

What cron expression runs a backup every night at 2am?

0 2 * * * runs a job at 02:00 every day. The five fields are minute, hour, day-of-month, month, and day-of-week — so 0 in the minute field and 2 in the hour field means "at exactly 2:00 AM," and the three remaining asterisks mean "every day, every month, every weekday." 2 AM is a common choice for backups because it typically falls in a low-traffic window for business applications, well after end-of-day activity and before the next morning's load.

How do I schedule weekly backups with cron?

Use the day-of-week field to pick a single day, for example 0 2 * * 0 runs at 2 AM every Sunday (0 = Sunday, 6 = Saturday in standard cron numbering). Weekly patterns are typically paired with a lighter daily job — a full backup on Sunday and incremental or differential backups the rest of the week — so you get complete recovery points without running an expensive full backup every night.

What is a good cron pattern for log rotation?

A common split is hourly size checks with 0 * * * * to catch runaway log growth quickly, plus a daily rotation job with 0 0 * * * that hands off to logrotate or a compression script. Most teams also add a retention rule — compress logs older than 7 days and delete anything older than 90 — so rotation frequency and retention length are handled as two separate settings, not one cron line.

How do I run a cron job every hour?

Set the minute field to a fixed value and leave the rest as asterisks: 0 * * * * runs at the top of every hour (1:00, 2:00, 3:00, and so on). Avoid * * * * * for maintenance tasks — that runs every minute, which is almost never what you want for backups, cache clearing, or health checks and can overwhelm a system if the job takes longer than a minute to finish.

What cron pattern avoids overlapping job runs?

Cron itself has no built-in overlap protection — it fires a new process at the scheduled time even if the previous run hasn't finished. The fix is inside the script, not the schedule: wrap the job body in a lock file check (flock is the standard tool on Linux) so a second invocation exits immediately if one is already running. Staggering start times for jobs that touch the same resources (database, disk I/O) also reduces the odds of a pileup in the first place.

What is the difference between a daily, weekly, and monthly cron tier?

Most production maintenance schedules use three tiers by cost and urgency: daily jobs (0 2 * * *) for cheap, essential tasks like incremental backups and log checks; weekly jobs (0 3 * * 0) for moderately expensive tasks like database optimization or full backups, usually run on a low-traffic day like Sunday; and monthly jobs (0 4 1 * *) for expensive or disruptive tasks like archive compaction or full security audits, run once on a fixed date such as the 1st. Tiering this way keeps the daily critical path fast while still covering deeper maintenance regularly.

How do I run a cron job on the first day of every month?

Set the day-of-month field to 1 and leave day-of-week as *: 0 4 1 * * runs at 4 AM on the 1st of every month. Watch the interaction between day-of-month and day-of-week — if you set both to specific values (not *), most cron implementations treat it as an OR, not an AND, which surprises people expecting "the first Monday of the month" behavior.

Should backup and log rotation cron jobs run at the same time?

No — stagger them. Running a database dump, a log rotation, and a cache clear all at 0 2 * * * competes for the same disk I/O and CPU, which can slow every job down or cause timeouts. A more reliable pattern spaces jobs 15–60 minutes apart (2:00 AM backup, 2:30 AM log rotation, 3:00 AM cache clear) so each finishes before the next resource-heavy task starts.

What cron pattern is best for SSL certificate renewal?

Certbot's own recommendation is to run its renewal check twice a day, since it only actually renews certificates within 30 days of expiry and is a no-op otherwise: 0 3 * * * and 0 15 * * * (3 AM and 3 PM). Running it twice daily costs nothing extra — the check is cheap — and gives redundancy if one run is missed due to a reboot or maintenance window.

cronbackupsmaintenancesystem administration