WordPress Backups You Can Actually Restore

Nobody has ever lost a website because they lacked backups. They lose websites because they lacked backups that restore — which is a different thing entirely. The graveyard of dead sites is full of people who had a backup plugin dutifully producing green checkmarks for two years, right up until the day they discovered the archives were missing the database, or stored on the same server that just died, or corrupted since March.

A backup is not a file. A backup is a tested capability to return to a known-good state within a known amount of time. Everything in this guide flows from that definition. If a practice doesn't improve your ability to actually get the site back, it's decoration.

What a complete WordPress backup contains

WordPress is two things pretending to be one: a set of files and a database. Losing either loses the site.

  • The database — every post, page, comment, user, setting, WooCommerce order, and form entry. This is the irreplaceable part. Your theme can be re-downloaded; your last five years of content cannot.
  • wp-content/uploads — the media library. Also irreplaceable, and usually the bulkiest part by far.
  • wp-content/themes and wp-content/plugins — technically re-downloadable, but only if you know the exact versions and nothing was customized. In practice: back them up, because 'we edited the theme once, years ago' is always discovered during a restore.
  • wp-config.php and server config — the file that glues it together, plus any .htaccess or nginx rules, cron entries, and PHP version notes. A restore onto a fresh server stalls for hours on exactly these details, so capture them.
  • WordPress core — genuinely re-downloadable. Including it makes restores simpler (one archive, no assembly); excluding it saves space. Either is fine as long as it's a decision.

The classic partial-backup failure: file-only backups made at the server level (the host copies the directory tree) that silently exclude the database, because the database lives in MySQL, not in the directory tree. If you don't know for certain your backup includes a .sql dump or equivalent, assume it doesn't and check today.

The 3-2-1 rule, translated for WordPress

The old sysadmin rule still earns its keep: 3 copies of your data, on 2 different kinds of storage, with 1 offsite. For a WordPress site, a sensible mapping:

  1. Copy 1: the live site itself (this counts).
  2. Copy 2: your host's automated backups — most managed hosts run nightly snapshots.
  3. Copy 3: an independent backup sent somewhere your host cannot touch — S3-compatible object storage, Google Drive, Dropbox, or a server at a different provider.

Copy 3 is the one people skip, and it's the one that matters most, because it's the only copy that survives the correlated failures: host goes out of business, account suspended over a billing dispute, hosting account compromised (attacker deletes backups first — this is standard practice in ransom scenarios), or the host's own backup system failing quietly. Host backups fail as a category precisely when you need them as a category. Independence is the feature.

One sharp edge: a backup plugin that writes archives to wp-content/backups on the same server has produced copy 1.5, not copy 3. Same disk, same server, same blast radius. Check where your archives actually land — the plugin's 'remote storage' tab either has credentials in it or it doesn't.

Frequency and retention: match the schedule to the loss you can tolerate

Ask one question: how much work am I willing to re-do? That number is your backup interval.

Site typeDatabaseFilesKeep
Brochure site, edited monthlyWeeklyWeekly8 weekly + 6 monthly
Active blog / content siteDailyWeekly (uploads change less)14 daily + 8 weekly + 6 monthly
WooCommerce / membershipHourly to real-timeDaily48 hourly + 30 daily + 12 monthly

Two principles hiding in that table. First, databases and files can run on different schedules — the database changes constantly and compresses small; uploads change rarely and weigh gigabytes. Splitting them makes frequent database backups nearly free. Second, retention depth matters more than people think. The nightmare scenario isn't 'server died last night' — that's the easy one, restore yesterday. It's 'the site was hacked, and we're not sure when.' If the compromise happened three weeks ago and you keep seven daily backups, every archive you own is infected. Malware discovery lag is why the monthly tier exists. Keep at least a few months of history; storage is cheap and hindsight isn't.

Choosing the mechanism

Three broad options, honestly compared:

Host-provided backups

Zero effort, usually well-engineered, restore with one click. Weaknesses: retention is often shallow (7–30 days), you can rarely download the raw archive easily, and they share fate with your hosting account. Use them — as copy 2, never as the whole plan.

Backup plugins

The pragmatic default for most site owners. A good plugin dumps the database, archives files, and ships everything to remote storage on schedule. Things to configure deliberately rather than accept: destination (remote, per above), schedule (split DB/files if supported), retention (the default is often laughably short), and email alerts on failure, not on success — 400 success emails train you to ignore the one that matters. Weakness to respect: plugins run inside PHP, so on very large sites they can hit memory and execution-time limits mid-archive, producing truncated files that look complete. Which is one more reason for the restore drill below.

Server-level scripts

For the comfortable-with-shell crowd: a cron job running wp db export (or mysqldump) plus an rsync or rclone of wp-content to object storage. Fastest, most reliable at scale, immune to PHP limits, and trivially scriptable across many sites. Weakness: you own it. When the cron dies silently after a server migration, no dashboard nags you — so pair it with an external monitor that alerts when a fresh backup doesn't appear (dead-man's-switch monitoring, not success logging).

The restore drill: the part everyone skips

Here is the uncomfortable claim at the heart of this guide: an untested backup should be assumed broken. Not because backup software is bad, but because the failure modes are silent and plentiful — truncated archives, missing database, incompatible PHP version on the restore target, serialized-data corruption after a URL change, forgotten wp-config values. None of these announce themselves until restore day.

So schedule restore day yourself, quarterly, before events do. The drill:

  1. Take a real archive from your remote storage — not the freshest local one. You're testing the copy you'd actually reach for in a disaster.
  2. Restore it somewhere that isn't production: a staging site, a cheap disposable VPS, or a local environment. Fresh WordPress-capable server, unpack files, import the database, adjust wp-config, update URLs if the environment differs (wp search-replace handles serialized data correctly; raw SQL find-and-replace does not — this bites everyone exactly once).
  3. Verify like a user, not an admin: log in, open five posts, check images render (uploads present?), submit a form, and on a store, place a test order. A homepage loading proves little; the damage hides in the corners.
  4. Time it and write it down. The stopwatch number is your real recovery time. If the answer is 'four hours, two of which were finding credentials,' you've learned that credentials belong in the runbook — a one-page document listing where archives live, how to access them, and the restore steps. Written for a stressed future-you, or better, for a colleague who isn't you at all.

The first drill is always humbling. That's the point — you want the humbling on a quiet Tuesday, not during the outage.

Special cases worth two extra minutes

  • WooCommerce and anything transactional: a restore rolls the database back, which means orders placed after the backup vanish while the payment processor still charged the cards. Real-time database replication or hourly backups shrink the window; either way, part of your runbook should be 'reconcile orders against the payment gateway after any restore.'
  • Before every update batch: a quick pre-update snapshot (host one-click or wp db export) turns 'the update broke the site' from an incident into an inconvenience. Cheapest insurance in WordPress.
  • Migrations and redesigns: take a full manual backup and keep it outside the normal rotation, labeled. Retention policies happily delete the 'last good copy before the redesign' right before you realize you need it.
  • Multisite: everything above, but restores of a single subsite from a network-wide backup are genuinely fiddly (shared users table, per-site table prefixes). Test that specific scenario, not just the full-network restore.

A checklist to steal

  1. Database and files both captured — verified by opening an archive, not by trusting a checkmark.
  2. At least one copy offsite, on infrastructure independent of your host.
  3. Schedule matched to how much work you can afford to lose; database more often than files.
  4. Retention includes monthlies going back several months, for the slow-discovery hack scenario.
  5. Alerting on failure or absence, not success.
  6. A one-page restore runbook a colleague could follow.
  7. A quarterly restore drill, timed, on a non-production target.

None of this is glamorous, and that's the highest praise available in this domain. Backups are the one part of running a website where boring is the entire objective: a dull green light, a dull quarterly drill, a dull one-page document — and then, on the day the disk dies or the hack lands or the intern deletes the wrong thing, the least dramatic disaster recovery anyone has ever seen. That's the goal. Test your restore this week; future-you is already grateful.

Photo: Zulfugar Karimov on Pexels