Skip to main content

WordPress Backup Plugins: Limitations and Best Use

WordPress backup plugins are convenient. They are often the wrong tool for reliable, daily, production-grade backups on a VPS. Most plugins default to full exports that run under PHP, store artifacts in or near the webroot, and do not provide the same verification and operational control as server-level tooling.

Quick Summary
  • Many plugins create a full archive on every run (inefficient for daily backups).
  • Backups created inside WordPress run under PHP limits (timeouts, memory limits, web server limits).
  • Storing backups under wp-content/ is a common security foot-gun.
  • Plugins can still be useful for migrations and one-click manual snapshots.
  • For VPS environments, prefer server-level backups (tar/zstd + mysqldump + offsite copy + verification).

What most backup plugins actually do

Many backup plugins follow this pattern:

  • walk the WordPress filesystem
  • export database to SQL
  • compress everything into a ZIP-like artifact
  • store the archive somewhere under wp-content/
  • optionally upload that archive to cloud storage

This approach is simple. It is also why it often becomes inefficient at scale.

Why full daily exports are inefficient

The key inefficiency is repeated work. If your site is 10 GB and you run a full export daily, you can end up producing and uploading 10 GB artifacts even if only a few MB changed.

Storage and bandwidth math

Example assumptions:

  • site files: 10 GB
  • database dump (compressed): 500 MB
  • daily full plugin export: 10.5 GB

Monthly impact:

plugin-full-export-math.txt
10.5 GB/day * 30 days = 315 GB of uploads per month
315 GB stored (or more, depending on retention)

Even if your cloud storage is cheap, your VPS I/O and CPU time are not free. Backups can become the busiest workload on the server.

Restores are not automatically better

Full archives are easier than incremental chains in theory. In practice, plugin restores can fail mid-flight due to timeouts or limits. That turns "simple" into "unreliable".

Where plugin backups break on VPS hosts

PHP execution limits

Plugin backups run in the same environment as your application. They inherit PHP limits like:

  • max_execution_time
  • memory_limit
  • FastCGI/web server timeouts
  • request body size limits during restore

Failure symptoms:

  • backup stuck at a percentage
  • HTTP 500 during backup
  • restore stalls at a percentage

Disk I/O pressure

Compressing large directory trees causes disk reads and writes. On busy WordPress servers, this can increase latency:

  • PHP-FPM workers slow down
  • MySQL queries slow down
  • page TTFB increases

If you run the backup during peak traffic, you can create a self-inflicted outage.

Temporary storage and double-write

Many plugins:

  • export DB to an intermediate file
  • compress files into an archive

That often means you need extra free disk space during the run. If the filesystem is near full, backups fail.

Shared hosting assumptions

Plugins are often designed to work without SSH. That pushes them toward strategies that are portable but not optimal for VPS operations.

Security risks you should take seriously

Backups inside the webroot

Some plugins store archives under:

  • wp-content/uploads/
  • wp-content/ai1wm-backups/
  • wp-content/wpvividbackups/
  • wp-content/updraft/

If those paths are web-accessible, your backups can be downloaded. Backups commonly contain:

  • the full database
  • wp-config.php
  • salts and keys
  • sometimes server logs

Mitigations:

  • store backup artifacts outside /var/www/html
  • restrict permissions
  • deny HTTP access (web server rules)
  • encrypt before offsite upload
warning

If an attacker can download your backup archive, assume the site is compromised. Change passwords, rotate keys, and treat it as a full incident.

Remote storage credentials

If a plugin stores long-lived cloud credentials and the site is compromised, attackers may:

  • download backups
  • delete backups
  • use your cloud resources for abuse

For offsite storage, prefer credentials that are:

  • scoped to a single bucket/folder
  • write-only when possible
  • easy to rotate

Feature gaps (what plugins often do not do well)

Not all plugins are the same. Use this section as an evaluation checklist.

Incremental file backups

Many plugins do not implement true incremental file snapshots. On a VPS, server-level tools can do it efficiently with rsync deltas.

Incremental database backups

Incremental DB backups require binlogs, PITR, or replication. Most plugins do not provide this.

Smart excludes

Excluding churn matters. Cache folders and nested backup archives inflate plugin backups.

Compression control

On VPS hosts, the best format for operational backups is often zstd. Plugins usually default to ZIP-like formats.

Verification and restore drills

Many plugins focus on "backup creation". Operationally, you want:

  • integrity tests (can it be decompressed?)
  • content tests (does it contain what you expect?)
  • restore drills (does it restore cleanly?)

Retention policies

Backups fill disks. Retention must be explicit and tested.

Plugin vs server-level: a capability matrix

This is a general comparison. Some plugins do better than others.

CapabilityPlugin backups (typical)Server-level backups
Runs without SSHyesno (usually)
Full backup on demandyesyes
Efficient daily file deltasoften noyes (rsync, snapshots)
DB dump controllimitedstrong (mysqldump, mariadb-dump)
Compression choicelimitedstrong (zstd, gzip, xz)
Store outside webrootsometimes hardeasy
Fine-grained excludeslimitedstrong
Offsite sync efficiencylimitedstrong (rclone, rsync)
Restore reliability at scalevariesstrong (if scripted)
Auditable logsvariesstrong
Encryptionvariesstrong (gpg, age)

When plugins are a good fit

Plugins can be the right tool when:

  • you are on shared hosting without SSH
  • you need a one-click migration package
  • you want a manual "before change" snapshot
  • your site is small and you can test restores easily

Common good uses:

  • migration/cloning
  • ad-hoc snapshots before risky changes
  • non-technical operators who need a simple restore UI

When plugins are risky

Be cautious if:

  • your site is large (multi-GB)
  • you run WooCommerce (transactional DB changes)
  • you have strict uptime requirements
  • backups must run unattended on a schedule

In these cases, plugin limitations become production risk.

A server-level strategy (efficient and safer)

This is the core idea:

  • DB: frequent full dumps (compressed)
  • Files: snapshot-style backups (rsync deltas)
  • Baseline: periodic full archives
  • Offsite: copy artifacts outside the VPS failure domain
  • Verification: integrity tests + restore drills

Tiered schedule example

ArtifactFrequencyWhy
DB dumpevery 1-6 hoursreduces data loss window
file snapshotdailycaptures new uploads and changes
full archiveweeklya simple baseline restore point
offsite copyafter each runsurvivability

Example commands (reference)

Files (tar.zst):

server-level-files-backup-example.sh
sudo tar -C /var/www/html -cf - . \
| zstd -3 -T0 -o "/backups/wp-files-$(date +%F).tar.zst"

Database (zstd):

server-level-db-backup-example.sh
mysqldump --single-transaction --quick --routines --events --triggers \
--column-statistics=0 wordpress \
| zstd -3 -T0 -o "/backups/wp-db-$(date +%F).sql.zst"

Offsite copy:

server-level-offsite-copy-example.sh
rclone copy /backups remote:wp-backups/site-a

Verification:

server-level-verify-example.sh
zstd -t /backups/wp-files-2026-03-01.tar.zst
zstd -t /backups/wp-db-2026-03-01.sql.zst

See the dedicated docs for full workflows:

  • opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/backup-logging-and-verification.mdx
  • opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/rsync-local-backup.mdx
  • opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/rclone-remote-targets.mdx

Migration plan: plugin to server-level

Use this sequence to avoid downtime.

Inventory current backups

  • where does the plugin store archives?
  • how often does it run?
  • how many versions does it keep?
  • have you ever restored from it?

Run both in parallel temporarily

Keep plugin backups while you stand up server-level backups. Do not remove the plugin schedule until you complete at least one restore drill from the new system.

Implement server-level artifacts

  1. create /backups with correct permissions
  2. create file archive + DB dump
  3. verify
  4. copy offsite
  5. verify offsite

Run a restore drill

Restore into staging directories/databases.

migration-restore-drill-files.sh
sudo rm -rf /tmp/restore-test
sudo mkdir -p /tmp/restore-test
sudo tar --use-compress-program=zstd -xf /backups/wp-files-2026-03-01.tar.zst -C /tmp/restore-test
sudo find /tmp/restore-test -maxdepth 3 -type d -name wp-content -print

Switch plugins to "manual only" (optional)

If you still want the plugin UI:

  • disable scheduled exports
  • keep it for manual snapshots/migrations
  • store outputs outside webroot if possible

If you must use a plugin, make it less dangerous

These practices reduce risk even if you keep plugin backups.

Store backups outside the webroot

If the plugin supports a custom backup path, choose something like /backups/plugin/.

If it does not, use web server rules to block access to the backup directory.

Reduce backup impact

  • run off-peak
  • exclude caches
  • keep retention small locally
  • move artifacts offsite quickly

Validate restores

At least monthly:

  • download one plugin archive
  • restore in a staging environment
  • document the steps

Deep dive: why PHP-based compression is fragile

PHP runtime limits and how they fail

Typical constraints:

  • PHP worker timeouts can kill long-running backups.
  • Memory limits can crash compression streams.
  • Web server request limits can block restore uploads.

Symptoms:

  • partial archives
  • missing files
  • restore fails halfway

Safer pattern on VPS:

  • run backups from cron/systemd
  • use OS tools (tar, zstd, mysqldump)
  • log exit codes

Deep dive: why backups under wp-content are risky

Common plugin backup paths and why they get exposed

Common paths:

  • wp-content/uploads/
  • wp-content/ai1wm-backups/
  • wp-content/wpvividbackups/
  • wp-content/updraft/

Why they get exposed:

  • uploads are often publicly readable
  • directory listings may be enabled
  • backup filenames are guessable

Mitigation:

  • store outside webroot
  • block access in web server config
  • encrypt archives

Troubleshooting

Plugin backups stuck at a percentage

Common causes:

  • filesystem near full
  • PHP timeout
  • memory limit
  • huge number of files

Immediate actions:

  • check disk space/inodes
  • move backups off-peak
  • reduce scope (wp-content only)
  • migrate to server-level
troubleshoot-disk-space.sh
df -hT
df -ih

Restore fails due to upload limits

Common causes:

  • request size limits
  • web server timeouts

On VPS, restore from the filesystem instead of through an HTTP upload.

Backups are huge

  • exclude caches
  • avoid nested backups
  • avoid including existing archives

See:

  • opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/excluding-folders.mdx

Practice lab

Use this lab to evaluate whether your plugin backups are usable.

  1. Locate the plugin backup directory.
  2. Copy one backup artifact to a safe location outside the webroot.
  3. Verify you can extract it.
  4. Verify the DB dump exists.
  5. Restore into staging.
lab-find-plugin-backup-folders.sh
sudo ls -lah /var/www/html/wp-content | sed -n '1,200p'
sudo find /var/www/html/wp-content -maxdepth 2 -type d -iname '*backup*' -print
lab-restore-to-staging-dir.sh
sudo rm -rf /tmp/restore-test
sudo mkdir -p /tmp/restore-test

# Replace archive name with your plugin artifact
sudo unzip /path/to/plugin-backup.zip -d /tmp/restore-test

sudo find /tmp/restore-test -maxdepth 3 -type d -name wp-content -print
warning

Do not restore into /var/www/html until you have validated the artifact in staging.


Plugin evaluation checklist (use this before you trust a plugin)

This checklist helps you evaluate whether a plugin can meet operational requirements.

If you cannot answer "yes" to the critical items, treat the plugin as a migration tool, not as your backup system.

Backup scope

CheckWhy it matters
Can you back up files and DB separately?DB and files have different change rates
Can you back up only wp-content/ intentionally?reduces size when core is reproducible
Can you exclude caches and temporary directories?prevents unnecessary growth
Can you exclude nested archives (*.zip, *.tar*)?avoids backup recursion

Storage placement

CheckWhy it matters
Can the plugin write to a path outside the webroot?prevents backup downloads via HTTP
Are backups protected from directory listing and direct URL access?reduces exposure
Can you enforce restrictive permissions (0600/0700)?backups often contain secrets

Performance controls

CheckWhy it matters
Can you schedule backups off-peak?reduces user impact
Can you control compression level/format?CPU/I/O cost varies
Can the job run without PHP timeouts?reliability of unattended runs
Can the plugin resume or retry safely?prevents partial artifacts

Offsite storage

CheckWhy it matters
Offsite upload uses robust transportavoids silent failures
Offsite credentials are scoped and rotatablereduces blast radius
Offsite deletion is controlledprevents accidental purge
You can verify remote copiesavoids "local only" failure

Verification and restore

CheckWhy it matters
Integrity verification existsdetect corrupt archives
You can extract/restore without the plugin UIrestores in emergencies
Restore drills are documented and repeatableactual RTO measurement

Observe resource impact (so backups do not become outages)

If you suspect plugin backups are hurting performance, observe CPU, memory, and I/O during a run.

observe-server-during-backup-run.sh
uptime
free -h
vmstat 1 5

ps -eo pid,user,pcpu,pmem,etime,cmd --sort=-pcpu | head -n 15
ps -eo pid,user,pcpu,pmem,etime,cmd --sort=-pmem | head -n 15

If wa (I/O wait) is high and the site slows down during backup runs, move the workload out of PHP and into scheduled server-level tooling.


Block plugin backup directories from HTTP

If you cannot relocate plugin backup paths outside the webroot, at least block them.

Nginx example

nginx-deny-backup-directories.conf
location ~* /(wp-content/(ai1wm-backups|wpvividbackups|updraft|backups))/ {
deny all;
return 403;
}

location ~* \.(zip|tar|gz|zst|wpress)$ {
deny all;
return 403;
}

Apache example

apache-deny-backup-directories.conf
<DirectoryMatch "wp-content/(ai1wm-backups|wpvividbackups|updraft|backups)">
Require all denied
</DirectoryMatch>

<FilesMatch "\.(zip|tar|gz|zst|wpress)$">
Require all denied
</FilesMatch>
warning

Blocking HTTP access reduces risk, but it does not solve the performance/reliability limits of PHP-based backups.


Reference: a complete server-level backup script (files + DB + offsite)

This example is intentionally verbose. Use it as a reference, then split responsibilities into smaller scripts if you prefer.

wp-backup-full-reference-script.sh
#!/usr/bin/env bash
set -euo pipefail

umask 077

SITE_ROOT="/var/www/html"
DB_NAME="wordpress"
BACKUP_DIR="/backups"
LOG_DIR="$BACKUP_DIR/logs"
STAMP="$(date +%F)"
HOST="$(hostname)"

FILES_ARCHIVE="$BACKUP_DIR/wp-files-${HOST}-${STAMP}.tar.zst"
DB_DUMP="$BACKUP_DIR/wp-db-${HOST}-${STAMP}.sql.zst"
LOG_FILE="$LOG_DIR/wp-backup-${HOST}-${STAMP}.log"

REMOTE="remote:wp-backups/site-a"

mkdir -p "$BACKUP_DIR" "$LOG_DIR"

{
echo "[$(date -Is)] start"
echo "host=$HOST"
echo "site_root=$SITE_ROOT"
echo "db=$DB_NAME"
echo "files_archive=$FILES_ARCHIVE"
echo "db_dump=$DB_DUMP"

echo "[$(date -Is)] create files archive"
tar -C "$SITE_ROOT" \
--exclude='wp-content/cache' \
--exclude='wp-content/*/cache' \
--exclude='wp-content/updraft' \
-cf - . \
| zstd -3 -T0 -o "$FILES_ARCHIVE"

echo "[$(date -Is)] create db dump"
mysqldump \
--single-transaction \
--quick \
--routines --events --triggers \
--column-statistics=0 \
"$DB_NAME" \
| zstd -3 -T0 -o "$DB_DUMP"

echo "[$(date -Is)] verify integrity"
zstd -t "$FILES_ARCHIVE"
zstd -t "$DB_DUMP"

echo "[$(date -Is)] list archive (spot check)"
tar --use-compress-program=zstd -tf "$FILES_ARCHIVE" | sed -n '1,25p'

echo "[$(date -Is)] artifact sizes"
ls -lh "$FILES_ARCHIVE" "$DB_DUMP"

echo "[$(date -Is)] offsite copy"
rclone copy "$BACKUP_DIR" "$REMOTE" \
--include "wp-files-${HOST}-*.tar.zst" \
--include "wp-db-${HOST}-*.sql.zst" \
--include "wp-backup-${HOST}-*.log"

echo "[$(date -Is)] verify offsite listing"
rclone lsf "$REMOTE" | sed -n '1,40p'

echo "[$(date -Is)] retention (local)"
find "$BACKUP_DIR" -maxdepth 1 -type f -name "wp-files-${HOST}-*.tar.zst" -mtime +30 -delete
find "$BACKUP_DIR" -maxdepth 1 -type f -name "wp-db-${HOST}-*.sql.zst" -mtime +30 -delete
find "$LOG_DIR" -type f -name "wp-backup-${HOST}-*.log" -mtime +30 -delete

echo "[$(date -Is)] done"
} | tee "$LOG_FILE"
warning

The retention lines permanently delete files. Run list-only versions first when adapting this script.


Restore testing pattern (what to prove)

If you want to trust backups during an incident, prove these in staging:

  • you can extract the files archive
  • the WordPress layout is present
  • you can import the DB dump into a staging DB
  • you can start services and load wp-login
restore-test-pattern.sh
set -e

sudo rm -rf /tmp/restore-test
sudo mkdir -p /tmp/restore-test
sudo tar --use-compress-program=zstd -xf /backups/wp-files-2026-03-01.tar.zst -C /tmp/restore-test

sudo find /tmp/restore-test -maxdepth 3 -type d -name wp-content -print
sudo find /tmp/restore-test -maxdepth 3 -type f -name wp-config.php -print

zstd -dc /backups/wp-db-2026-03-01.sql.zst | mysql wordpress_restore

Decision guide

Use this as a fast "what should I do" chart.

Your situationRecommended approach
Shared hosting, no SSHplugin backups + offsite copies, frequent restore drills
VPS, low-change siteserver-level full backups + offsite
VPS, large media siteserver-level snapshots + offsite, avoid PHP compression
WooCommercefrequent DB dumps + snapshots + offsite, consider HA for low RTO
Strict uptime requirementsHA design + backups + drills

Next steps

  • Backup types and schedules: opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/full-vs-incremental-vs-differential.mdx.
  • 3-2-1 design: opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/321-backup-strategy-for-wp.mdx.
  • Logging and verification: opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/backup-logging-and-verification.mdx.
  • Disaster recovery workflow: opt/docker-data/apps/docusaurus/site/docs/server/linux-server/10-backup-disaster-recovery/disaster-recovery-workflow.mdx.