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:
- Where are backups stored? On the same server? Off-site? Multiple locations?
- Are database and files both included? Many plugins only back up the database.
- How often do they run? Daily? Hourly? Only during quiet hours?
- How long are they retained? Seven days? Thirty? Ninety?
- Has anyone tested a restore? Not a file check — an end-to-end restore to a clean server.
- Who gets alerted when backups fail? Does the alert reach someone who can act?
- 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:
| Requirement | Baseline | Better |
|---|---|---|
| Database backup | Daily | Every 6 hours |
| File backup | Daily | Incremental every 6 hours |
| Off-server storage | Yes (S3, R2, Google Drive, SFTP) | Multi-region or multi-provider |
| Retention | 14 days | 30 days + monthly archives |
| Restore test | Quarterly | Monthly automated restore and smoke test |
| Alerting | Email on failure | Uptime monitor + Slack/Telegram alert |
| Documentation | Written steps | Video 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
| Storage | Good for | Watch out for |
|---|---|---|
| AWS S3 / Cloudflare R2 | Reliable, versioned, cheap | Need to configure lifecycle rules |
| Google Drive | Easy, human-browsable | Shared account access, quota limits |
| SFTP to another server | Direct, no third party | Server-to-server dependency |
| Backup plugin’s own cloud | Convenient, bundled | Vendor lock-in, harder to audit |
| Local + rsync off-server | Fast local restore, remote copy | Extra 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:
- Plugin-level alerts — Email on failure to a distribution list, not one person
- Monitoring service — UptimeRobot, HetrixTools, or similar to check for stale backup files
- 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.