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.
From your WordPress admin (most common)
- Go to Plugins → Add New Plugin.
- Search for "RestorePilot".
- Click Install Now, then Activate.
- Go to RestorePilot in the admin menu and create your first backup.
Manual install (if you downloaded the zip separately)
- Upload the
restorepilot-backup-migration folder to /wp-content/plugins/, or upload the zip directly via Plugins → Add New Plugin → Upload Plugin.
- Activate the plugin through the Plugins screen.
- Go to RestorePilot in the admin menu and create your first backup.
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
== Upgrade Notice ==
0.5.9
Fixes Master Reset's "also delete stored backups", which did nothing on sites whose backups had moved out of the uploads directory — meaning any site that has run 0.5.7. It reported success while leaving every backup on disk. Uninstall was not affected.
0.5.8
Fixes two ways stored backups were kept when you asked for them to be deleted: uninstalling the plugin, and Master Reset. Large downloads are now checked on each request rather than left at a public address. Restore reliability and dialog keyboard handling improved.
0.5.0
Removes the size limits on backup and restore: backups split into volumes, the database is streamed, and background jobs resume after a host timeout. Keep all volumes of a backup together. Includes a security fix for crafted archives. Requires WordPress 6.2+.
0.3.1
Important fix: selected-folder backups now preserve plugin folder paths, so backup plugin code is included while backup archives remain excluded. Also cleans missing active plugin references after restore.