RestorePilot Backup & Migration

Description

RestorePilot Backup & Migration is a straightforward backup and restore plugin for WordPress site owners, developers, and small agencies.

It creates a downloadable backup package containing this site’s WordPress database tables and, optionally, the wp-content files. During restore, RestorePilot automatically detects the source URL from the backup manifest and replaces it with the current site URL using serialized-safe replacement — no manual search-and-replace needed.

Why RestorePilot

Most backup plugins are tested by how well backups work. Restores get tested less, and that is the moment you actually need one to work.

  • A rollback point before every restore. RestorePilot saves your current database before it changes anything, and you can restore straight from it if something goes wrong — no separate backup step, no remembering to do it yourself.
  • Resumes instead of restarting. A host timeout, a closed browser tab, a slow connection — collecting files and restoring both pick up from where they stopped, and a restore continues partway through a single large database table. The one step that does not resume is the database export inside a backup: it is taken as a single consistent snapshot, which cannot outlive the process that opened it, so if that step is cut short it starts again rather than stitching together tables read at different moments.
  • Volume splitting for large sites. Backups are split into volumes automatically, so a host’s per-file size limit stops being a reason a backup can fail. Free disk space, rather than file size, becomes the limit.
  • Nothing leaves your server. Backups are written to your own server, in a directory beside WordPress where the web server cannot serve them, falling back to the uploads directory if that is not writable. RestorePilot has no cloud storage integration and sends nothing to the plugin author or any third party — see Privacy & data below.
  • Built for migration, not just backup. Source and target URLs are detected automatically from the backup itself, with serialized-safe replacement across options, widgets, and post meta — restoring a backup on a different domain does not need a manual search-and-replace pass.

Features

Backup

  • Full site backup: database + wp-content files.
  • Split into volumes: a site is limited by free disk space rather than by how large a single file the server allows.
  • Constant memory use: the database is exported and restored as a stream, so database size is not limited by PHP’s memory limit. Backups taken by much older versions used a single-document format that has to be read whole; those are still restorable, but their size is limited by memory, and RestorePilot refuses one it cannot decode before touching the site rather than failing part way.
  • Resumes automatically: if a background backup is interrupted by a host timeout, file collection continues from where it left off. The database export is the exception — it runs as one consistent snapshot and restarts if interrupted, which is the price of every table being read as of the same moment. A scheduled daily backup runs as a single process and does not resume at all.
  • One-click full backup download for restore or migration.
  • Advanced file selection: choose which top-level wp-content folders to include.
  • Friendly backup filenames with site name and date/time.
  • Background backup jobs — navigating away does not cancel the backup.
  • Progress bar with percent complete and estimated time remaining.
  • Cancel button for running backups.
  • Health check before restore to verify backup integrity.
  • Free version keeps the newest 2 backups total across manual and daily backups.

Restore & Migrate

  • Restore from an uploaded backup zip.
  • Large uploads are sent in smaller chunks to bypass PHP upload limits.
  • Restore from a zip already inside the site’s uploads directory (useful for very large sites).
  • Auto-detect source and target URLs from the backup manifest.
  • Manual source/target URL mode for advanced migrations.
  • Serialized-safe URL replacement (handles WordPress options, widgets, post meta).
  • Table prefix mapping between source and target sites.
  • Pre-restore database rollback point for safety.
  • Resumes automatically: if a background restore is interrupted by a host timeout, it continues from where it left off — including partway through a large table — on the next attempt instead of starting over. Each resumption re-reads the rows it has already written in order to find its place, so a table of several hundred thousand rows restores more slowly the more times it is interrupted.
  • Atomic table swap: new tables are staged before replacing live ones.
  • Maintenance mode during restore, automatically removed on completion or failure.
  • Post-restore success dialog after login.
  • The database is fully replaced by the backup. wp-content files are overlaid: files present in the backup overwrite matching files on the target, but a file that exists on the target and is not in the backup is left in place, not removed.

Downloads

  • Full backup zip is the primary download for restore and migration.
  • Advanced downloads for database, plugins, themes, uploads, must-use plugins, and other wp-content files.
  • Large backups are handed off to the web server where possible.
  • Resumable PHP streaming with HTTP Range support as a fallback.

Scheduled backups & notifications

  • Optional daily automatic backups via WP-Cron from the Daily Backup tab.
  • Optional email notification after backup success or failure.

Logs & diagnostics

  • Logs tab with refresh, download, clear, and quick filters.
  • Dark-themed log viewer for easy reading.
  • Database-backed fallback log if file logging fails.
  • System Readiness panel: PHP version, ZIP support, disk space, backup folder, WP-Cron.
  • Diagnostics & Maintenance panel for backup storage status, temp cleanup, stuck runtime reset, and log tools.
  • Runtime PHP warning and fatal error logging during RestorePilot actions.

WP-CLI

  • wp restorepilot backup — create a full backup.
  • wp restorepilot backup --db-only — database-only backup.
  • wp restorepilot health — check the newest backup.

Security & compatibility

  • Admin-only access with nonce verification on every action.
  • Backup storage protected by .htaccess and index.php.
  • Randomised backup filenames to reduce direct-access risk.
  • Installed backup plugins (UpdraftPlus, Duplicator, WP Staging, etc.) are
    backed up normally; only their stored backup archives are excluded from
    RestorePilot backups to avoid backup-of-backups bloat.
  • Missing active plugin references are cleaned after restore to avoid WordPress
    deactivating unavailable plugins with a scary admin notice.
  • Full cleanup on uninstall: backups, logs, temp files, options, scheduled events.
  • Multisite compatible uninstall. Note: creating backups and running restores is not supported on multisite networks.

Important note

This is an early release. Always test restores on a staging site before using RestorePilot on a production site.

Privacy & data

RestorePilot creates backup files that may contain personal data from your WordPress database, media library, themes, plugins, and uploaded files. Backups are stored locally on your own server, in a restorepilot-private-storage directory beside the WordPress installation so that no URL reaches them; if that location cannot be written, they stay in a protected folder inside the uploads directory instead. They remain there unless you download or move them yourself. RestorePilot does not send backup data to the plugin author or to any third-party service.

Deleting the plugin removes the stored backups along with it, from either location. A storage directory you configured yourself with RESTOREPILOT_STORAGE_DIR is left untouched, since it is yours rather than the plugin’s.

Screenshots

Installation

From your WordPress admin (most common)

  1. Go to Plugins Add New Plugin.
  2. Search for “RestorePilot”.
  3. Click Install Now, then Activate.
  4. Go to RestorePilot in the admin menu and create your first backup.

Manual install (if you downloaded the zip separately)

  1. Upload the restorepilot-backup-migration folder to /wp-content/plugins/, or upload the zip directly via Plugins Add New Plugin Upload Plugin.
  2. Activate the plugin through the Plugins screen.
  3. Go to RestorePilot in the admin menu and create your first backup.

FAQ

Does RestorePilot support migrations to a different domain?

Yes. RestorePilot stores the source site URL in the backup manifest and replaces it with the current site URL during restore — automatically.

Do I need to enter old and new URLs manually?

No. Auto-detect is on by default. Manual URL fields are available in Advanced restore settings for edge cases.

Does it handle serialized WordPress data?

Yes. URL replacement is applied after unserializing values where possible, then the values are serialized again. Incomplete PHP classes are safely skipped.

Where are backups stored?

In a restorepilot-private-storage directory next to your WordPress installation — outside the web root, so no request can reach a backup even on servers that ignore .htaccess, which is most of them. If that directory cannot be created or written, RestorePilot falls back to a protected restorepilot-backup-migration folder under the uploads directory and says so on the Status tab.

Either way the folder is excluded from future RestorePilot backups. You can choose the location yourself by defining RESTOREPILOT_STORAGE_DIR in wp-config.php; a directory you name that way is never deleted by the plugin, including on uninstall.

Why is a large download slower than it used to be?

Every download now goes through WordPress, which checks that you are still allowed to have the file on each request. Earlier versions handed very large archives straight to the web server instead, which was faster but meant the download address kept working until a scheduled cleanup removed it — and on sites where WP-Cron is disabled or traffic is low, that could be a long time. A backup contains your whole database, so the link is checked rather than merely deleted later.

Downloads are resumable: if a transfer is interrupted, your browser or download manager can continue it rather than starting again. If your host cuts off long requests and a large download will not complete, split the backup into volumes and fetch the parts, or re-enable the direct route by adding this to wp-config.php:

define('RESTOREPILOT_DIRECT_DOWNLOADS', true);

That trades the confidentiality of the download link for reliability on a slow host. Turn it on only if you need it.

Are other backup plugins’ files excluded from the backup?

RestorePilot excludes the backup archives created by other plugins (UpdraftPlus, Duplicator, BackupBuddy, WP Staging, etc.) to avoid including huge backup zips inside your backup. The backup plugins themselves (their code inside wp-content/plugins/) are included normally.

What happens when I delete the plugin?

Deleting the plugin removes all RestorePilot backups, logs, temporary download files, background job data, backup locks, and scheduled events.

My backup is larger than the browser upload limit. What do I do?

Two options: (1) RestorePilot automatically splits large uploads into chunks if you upload a single zip larger than the server limit. (2) Upload the zip into this site’s WordPress uploads directory via FTP/SFTP and use Advanced restore settings Server backup path during restore.

Why is my backup split into several files?

Many hosts refuse to create a file beyond a fixed size — the write fails with “File too large” no matter how much free disk space there is. RestorePilot therefore writes a backup as a set of volumes of up to 1 GB each: your-backup.zip, your-backup-v002.zip, and so on. A small site produces a single file and looks exactly as before.

Keep the whole set together. To restore, place every volume in the same folder — RestorePilot reads them as one backup, and refuses to start if any volume is missing rather than restoring part of your site. If your host has a lower file size limit, a developer can reduce the volume size with the restorepilot_backup_volume_bytes filter.

You never need to handle the volumes yourself: “Download Full Backup” always gives you a single file, even when the backup behind it is stored as several volumes — RestorePilot reassembles them into one download automatically. The individual volumes are still available under “Download volumes individually” if you ever need to retry just one piece.

My backup or restore shows “continuing in the background” instead of finishing right away — is that normal?

Yes. A background backup or restore runs in short chunks rather than one long process, so a host execution-time limit, a proxy or CDN timeout, or anything else that cuts the process short does not lose the work already done — the next chunk continues from where the last one stopped, including partway through a single large database table during a restore. On a large site this can mean several chunks before the job finishes, which is expected and does not mean anything went wrong.

Two things do not resume, and it is better to know which. The database export inside a backup is taken as one consistent snapshot; a database transaction cannot outlive the PHP process that opened it, so if that step is cut short it starts again rather than joining together tables read at different moments. And a scheduled (cron) daily backup runs as a single process throughout, so it does not chunk or resume at all.

A restore also finds its place on each resumption by re-reading the rows it has already written, so a very large single table takes longer the more times the restore is interrupted.

Can I check a backup before restoring?

Yes. Click Health Check next to any backup. RestorePilot verifies the zip structure, manifest, database export, and file paths.

How many backups does RestorePilot keep?

The free version keeps the newest 2 backups total. Manual backups and daily automatic backups share the same limit; older backups are removed automatically.

Can I run backups from WP-CLI?

Yes. Use wp restorepilot backup for a full backup, wp restorepilot backup --db-only for database only, and wp restorepilot health to check the newest backup.

What happens if a restore fails?

RestorePilot stops immediately, removes maintenance mode, and writes the full error to the Logs tab. A pre-restore rollback point may be available, but you should review the logs and verify the site before retrying.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“RestorePilot Backup & Migration” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

0.5.9

  • Fixed: Master Reset’s “also delete stored backups” now actually deletes them. The fix released in 0.5.8 did not work on any site whose backups had been moved out of the uploads directory, which is every site that has run 0.5.7. The reset wipes the plugin’s settings before it deletes the backups, and the setting it wipes is the one recording where the backups were moved to — so by the time it went to delete them, nothing knew where they were. It reported success regardless. Uninstall was not affected and has worked since 0.5.8. If you have run a Master Reset with that box ticked since updating to 0.5.8, your backups are still on the server, in a restorepilot-private-storage directory beside your WordPress folder; running the reset again on 0.5.9 will remove them, or you can delete that directory yourself.

0.5.8

  • Fixed: deleting the plugin now removes your stored backups, and Master Reset’s “also delete stored backups” now actually deletes them. Moving backups out of the uploads directory in 0.5.7 left both of these looking in the old place, so archives were kept while the plugin said it had removed them. Master Reset even wrote “Stored backups were deleted at the operator’s request” into the log while leaving every one of them on disk. A backup contains your whole database, so a copy left behind on a site you have handed over or deleted the plugin from matters. A storage directory you set yourself with RESTOREPILOT_STORAGE_DIR is never removed by either, because it is yours rather than the plugin’s.
  • Security: large backup downloads are checked on every request instead of being placed at a secret web address that a scheduled cleanup deleted six hours later. Where WP-Cron is disabled or the site is quiet, that address kept working. Downloads are resumable, so an interrupted transfer continues rather than restarting. If your host cuts off long downloads, split the backup into volumes, or add define('RESTOREPILOT_DIRECT_DOWNLOADS', true); to wp-config.php to restore the old behaviour.
  • Fixed: a restore now refuses a backup in the old single-document format that is too large for your server’s PHP memory limit, and says what to do about it, instead of accepting it and running out of memory part-way through with the site already in pieces. Backups taken by any recent version stream and are unaffected.
  • Fixed: the files a restore needs in order to be resumed or monitored are now written and checked properly. They are the only record that survives the moment a restore replaces the database, and a failed write was previously ignored, which could leave a restore that could not continue and whose progress could not be read.
  • Fixed: the confirmation dialogs now behave like dialogs. Keyboard focus stays inside them, Escape closes them, and focus returns to the control that opened them; the page behind can no longer be reached with the keyboard or a screen reader.
  • Fixed: when a restore has to invent an administrator email address because none was usable, that address is now valid on sites whose address has no dot in it, such as a local development install at localhost.
  • Changed: the plugin’s own description, privacy text and FAQ now describe where backups are actually kept and what is removed when you delete the plugin.

0.5.7

  • Security: your backups are no longer kept where the web server can hand them out. They were stored under wp-content/uploads, protected by an .htaccess file — which Apache honours and nginx ignores completely. On nginx, which is what most managed WordPress hosting runs, a backup could be downloaded by anyone who knew or guessed its address; the only thing standing in the way was the filename. A backup contains your whole database, including every user account and password hash. Backups are now kept in a directory beside your WordPress installation, which your site has no web address for, and existing backups are moved there automatically the next time you open the plugin. Downloading through the plugin is unchanged and has always required you to be logged in as an administrator.
  • Added: where your host does not allow a directory outside the site to be created, backups stay where they are and RestorePilot now says so in the log instead of assuming the .htaccess protected them. It checks by placing a file in the backup folder, requesting it over the web, and reporting what came back.
  • Note: the move copies every file and verifies it has arrived before changing anything, and only removes the originals once the whole set is safely in place. If it cannot finish, nothing is changed and your backups stay exactly where they were.

0.5.6

  • Fixed: the manual installation instructions in the repository README left out the includes/ directory, which the plugin loads eighteen files from. Anyone following them got a fatal error instead of a working plugin. Installing through WordPress was never affected.
  • Fixed: a restore now enforces its own limits by looking at the backup rather than by believing what the backup says about itself. The number of database tables was checked against a figure the archive declared, so an archive that understated it could grow the restore’s working set until PHP ran out of memory. Tables are counted as they are read now, and an archive that unpacks to more than two hundred times the space it occupies is refused before anything is written to disk. A single database record longer than 64 MB is also refused rather than read whole. These protect against a damaged or crafted archive; a backup this plugin produced is unaffected, and reading the database export is now faster than before.
  • Fixed: when Master Reset is asked to remove must-use plugins, anything it cannot delete is now named in the result. It previously reported only how many it had removed, so a file left behind was invisible while the reset still described the site as clean. A must-use plugin loads on every request, so one left behind is still running.
  • Changed: development and test material is now excluded from the released package by an explicit list of what may be included, with the contents checked on every commit rather than at release time. No release has ever contained it; this makes that a property of the build instead of something remembered by hand.

0.5.5

  • Fixed: a restore could stop partway with a “Duplicate entry” database error, and sometimes then report that a table was missing. When a restore continues in the background it may be picked up by two workers at once — one sent directly, one from the scheduled fallback — and both would write the same rows to the same temporary table. A row that has already been written is now recognised as such and the restore carries on, rather than treating it as a failure. Every other database error still stops the restore, and the log records when a table was written twice. This affects 0.5.3 and 0.5.4; whether it happened depended on timing, and it became more likely the larger the site. Note that this protection needs a table to have a primary or unique key to identify its rows by — a small number of plugin tables have neither, and a restore of those can still stop this way.
  • Added: the password for a new administrator account can now be shown while you type it. That password is needed immediately after the restore, to sign in to a site whose address may have just changed, with no other administrator to fall back on — so a typo you cannot see locks you out.
  • Fixed: after restoring a backup uploaded from your computer, the “Server backup path” box under Advanced settings was left holding an internal temporary filename, pointing at a file the restore had already deleted. Starting another restore without choosing a new file then failed. That box is now only ever what you type in it.
  • Changed: Master Reset has moved out of the Status tab into a Danger Zone tab of its own. Everything in front of it is unchanged: the warning, the confirmation dialog, the acknowledgement, and typing RESET in full. Removing your stored backups and your must-use plugins both remain off unless you tick them.

0.5.4

  • Fixed: cancelling a backup did not stop it. Cancel marked the backup cancelled, but the process doing the work never saw that. It was reading a copy of the job made when its turn started, and its own progress updates — which happen every few seconds — then wrote “still running” back over the cancellation. The backup carried on to the end. Cancelling now takes effect within about a second.
  • Fixed: ending a stuck restore from the maintenance screen did not stop the restore. Ending it released the locks that keep two restores apart, but the process still doing the work carried on writing to the database for the rest of its turn, unaware. A restore started straight afterwards could therefore run alongside one that had not actually stopped, which is how a database ends up holding tables from two different backups. The work now stops within about a second of being ended. If you have ever ended a restore and immediately started another, compare your data against a pre-restore rollback point before trusting it.
  • Fixed: a restore could lose its record of how far it had got when more than one process was involved, causing it to repeat work it had already finished. The same cause as the two above: each update to a job’s record was built on a copy that could be out of date, so one process could erase what another had just written.
  • Added: Master Reset can now remove must-use plugins, which it previously always left in place — so a site it described as clean still had every one of them loading on every request. This is off unless you tick it, and the confirmation lists them by name rather than as a count, because some are installed by your host or by a site-management service and deleting those can break things you cannot reinstall yourself.

0.5.3

  • Fixed: the duplicate-entry error during a restore that 0.5.2 claimed to fix was not actually fixed. The correction there re-read the restore’s saved position after taking the lock that makes a worker the only one running, but WordPress caches that read within a request, so it handed back the same stale copy it already had and two workers could still resume from the same place. It now reads past the cache.
  • Fixed: starting a restore while another was still finishing could make the new one delete the tables the old one was still writing to, failing it with a missing-table error. Each restore now tracks its own scratch tables, and the cleanup that removes leftovers skips any restore that is still going.
  • Fixed: Master Reset deleted RestorePilot itself, along with the other plugins it is meant to remove. Reorganising the code in 0.5.2 moved the check that told the reset which plugin folder was its own, so it stopped recognising itself. If you ran Master Reset on 0.5.2 the plugin was removed but your stored backups were not — reinstall RestorePilot and they will still be listed. Six other places that located the plugin’s own files the same way were corrected at the same time, including the one a restore uses to avoid overwriting the plugin while it is running.
  • Added: Master Reset can now also delete RestorePilot’s own stored backups and rollback points, for when a site is being handed to someone else and should not carry copies of the previous content. It is off by default and has to be ticked deliberately, because those backups are the only way to undo a reset.

Older releases (0.5.2 down to 0.1.0) are listed in changelog.txt in the plugin’s
repository: https://github.com/srj2326/restorepilot/blob/main/changelog.txt