A backup plugin is not a backup strategy. The useful question is whether you can restore the site quickly when something breaks. Most backup failures are discovered during incidents, not during scheduled tests.

The seven essential questions

Before trusting a backup setup, answer these:

  1. Where are backups stored? On the same server? Off-site? Multiple locations?
  2. Are database and files both included? Many plugins only back up the database.
  3. How often do they run? Daily? Hourly? Only during quiet hours?
  4. How long are they retained? Seven days? Thirty? Ninety?
  5. Has anyone tested a restore? Not a file check — an end-to-end restore to a clean server.
  6. Who gets alerted when backups fail? Does the alert reach someone who can act?
  7. Is the backup process documented? Can someone else restore if you are unavailable?

The dangerous pattern

The most common failure mode: a backup plugin writes backups to the same server and nobody ever checks them. If the server dies, fills up, or is compromised, the backups go with it.

Specific red flags:

  • Backups stored in wp-content/uploads/backup/ on the production server
  • No off-server copy
  • Backup emails going to an unmonitored inbox
  • Backup size growing unchecked until the disk fills
  • Silent failures that nobody notices for weeks

Minimum standard

For a normal business WordPress site, the minimum is:

RequirementBaselineBetter
Database backupDailyEvery 6 hours
File backupDailyIncremental every 6 hours
Off-server storageYes (S3, R2, Google Drive, SFTP)Multi-region or multi-provider
Retention14 days30 days + monthly archives
Restore testQuarterlyMonthly automated restore and smoke test
AlertingEmail on failureUptime monitor + Slack/Telegram alert
DocumentationWritten stepsVideo walkthrough + runbook

For WooCommerce, membership, or LMS sites: increase database backup frequency to match transaction volume. Losing 24 hours of orders is unacceptable for most ecommerce.

Real storage options

StorageGood forWatch out for
AWS S3 / Cloudflare R2Reliable, versioned, cheapNeed to configure lifecycle rules
Google DriveEasy, human-browsableShared account access, quota limits
SFTP to another serverDirect, no third partyServer-to-server dependency
Backup plugin’s own cloudConvenient, bundledVendor lock-in, harder to audit
Local + rsync off-serverFast local restore, remote copyExtra setup, needs two jobs

At minimum, use two destinations: one convenient (plugin’s cloud or S3) and one independent (SFTP to a different provider or a manual monthly export to cold storage).

Verify restorability: the drill

Do not wait for an incident. Schedule a test restore:

# 1. Create a fresh test server or local Docker environment
# 2. Download the most recent backup
# 3. Import the database
mysql -u root -p wordpress_test < backup.sql

# 4. Restore files
rsync -a backup/wp-content/uploads/ wp-content/uploads/

# 5. Fix permissions
chown -R www-data:www-data wp-content/uploads
find wp-content/uploads -type d -exec chmod 755 {} \;
find wp-content/uploads -type f -exec chmod 644 {} \;

# 6. Update URLs if testing on a different domain
wp search-replace example.com staging.example.com

# 7. Test the site
curl -s -o /dev/null -w "%{http_code}" https://staging.example.com

Checklist after restore:

  • Homepage loads
  • Admin login works
  • Media files render
  • Contact forms submit
  • WooCommerce products display
  • Checkout works (test mode)
  • Cache flushes cleanly
  • Error logs are quiet

Alerting that actually works

A backup failure alert is useless if nobody sees it. Set up:

  1. Plugin-level alerts — Email on failure to a distribution list, not one person
  2. Monitoring service — UptimeRobot, HetrixTools, or similar to check for stale backup files
  3. Heartbeat test — A simple script that checks if the most recent backup is newer than 25 hours and reports if not:
#!/bin/bash
BACKUP_DIR="/mnt/backups/example.com"
LATEST=$(find "$BACKUP_DIR" -name "*.sql.gz" -mtime -1 | head -1)
if [ -z "$LATEST" ]; then
  echo "BACKUP MISSING: No backup in last 24h for example.com"
  exit 1
fi

Cleanup and retention

Backups can silently consume disk space. Set up cleanup:

# Delete backups older than 30 days
find /mnt/backups/example.com -name "*.sql.gz" -mtime +30 -delete
find /mnt/backups/example.com -name "*.tar.gz" -mtime +30 -delete

For S3 or R2, use lifecycle rules to auto-expire old objects. Do not rely on the backup plugin’s retention settings alone — verify they actually work by checking storage after a month.

When to upgrade from plugin backups

Plugin-based backups work well for most small and mid-size sites. Consider server-level or external backups when:

  • The site is larger than 5 GB in uploads
  • Database is larger than 1 GB
  • Backup windows conflict with traffic patterns
  • You need point-in-time recovery (binary log + snapshots)
  • Compliance requires encrypted, immutable backups

Server-level options: mysqldump + rsync, restic, borgbackup, provider snapshot APIs, or managed database backup services.

A backup that has never been tested is not a backup — it is a hope.