{"id":332373,"date":"2026-08-24T20:15:47","date_gmt":"2026-08-24T20:15:47","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/restorepilot-backup-migration\/"},"modified":"2026-08-25T12:28:32","modified_gmt":"2026-08-25T12:28:32","slug":"restorepilot-backup-migration","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/restorepilot-backup-migration\/","author":23512641,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.5.0","stable_tag":"0.5.0","tested":"7.0.4","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"RestorePilot Backup & Migration","header_author":"Surajit Roy","header_description":"Back up, restore, and migrate WordPress sites with serialized-safe URL replacement.","assets_banners_color":"145d94","last_updated":"2026-08-25 12:28:32","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/profiles.wordpress.org\/srjdev\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":54,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.5.0":{"tag":"0.5.0","author":"srjdev","date":"2026-08-25 12:28:32"}},"upgrade_notice":{"0.5.0":"<p>Removes the size limits on backup and restore: backups are split into volumes, the database is streamed, and both a background backup and a background restore now resume automatically if the host interrupts them, so neither file size, PHP memory, nor a host timeout caps the site size. Keep all volumes of a backup together. Includes a security fix for crafted archives. Requires WordPress 6.2+.<\/p>","0.3.1":"<p>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.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3664244,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3664244,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3664244,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3664244,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.5.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3664270,"resolution":"1","location":"assets","locale":"","width":1147,"height":736},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3665376,"resolution":"2","location":"assets","locale":"","width":1211,"height":1088},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3664270,"resolution":"3","location":"assets","locale":"","width":1138,"height":806},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3664270,"resolution":"4","location":"assets","locale":"","width":674,"height":888},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3664270,"resolution":"5","location":"assets","locale":"","width":1130,"height":1278},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3664270,"resolution":"6","location":"assets","locale":"","width":641,"height":657}},"screenshots":{"1":"Backup tab \u2014 create a full or custom backup, and download, check, restore, or delete the backups you already have.","2":"Daily Backup tab \u2014 schedule one automatic backup a day and get an email when it succeeds or fails.","3":"Restore tab \u2014 restore from an uploaded zip or from one already on the server, with automatic URL detection for migrations.","4":"Every restore is confirmed first \u2014 what will change, how to recover if it fails, and a required acknowledgement.","5":"Status tab \u2014 system readiness, storage and rollback diagnostics, and safe maintenance tools.","6":"Destructive actions ask twice \u2014 Master Reset requires both a backup acknowledgement and typing RESET."}},"plugin_section":[],"plugin_tags":[151,10718,4155,152,23756],"plugin_category":[59],"plugin_contributors":[277314],"plugin_business_model":[],"class_list":["post-332373","plugin","type-plugin","status-publish","hentry","plugin_tags-backup","plugin_tags-database-backup","plugin_tags-migration","plugin_tags-restore","plugin_tags-site-migration","plugin_category-utilities-and-tools","plugin_contributors-srjdev","plugin_committers-srjdev"],"banners":{"banner":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/banner-772x250.png?rev=3664244","banner_2x":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/banner-1544x500.png?rev=3664244","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/icon-128x128.png?rev=3664244","icon_2x":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/icon-256x256.png?rev=3664244","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-1.png?rev=3664270","caption":"Backup tab \u2014 create a full or custom backup, and download, check, restore, or delete the backups you already have."},{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-2.png?rev=3665376","caption":"Daily Backup tab \u2014 schedule one automatic backup a day and get an email when it succeeds or fails."},{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-3.png?rev=3664270","caption":"Restore tab \u2014 restore from an uploaded zip or from one already on the server, with automatic URL detection for migrations."},{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-4.png?rev=3664270","caption":"Every restore is confirmed first \u2014 what will change, how to recover if it fails, and a required acknowledgement."},{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-5.png?rev=3664270","caption":"Status tab \u2014 system readiness, storage and rollback diagnostics, and safe maintenance tools."},{"src":"https:\/\/ps.w.org\/restorepilot-backup-migration\/assets\/screenshot-6.png?rev=3664270","caption":"Destructive actions ask twice \u2014 Master Reset requires both a backup acknowledgement and typing RESET."}],"raw_content":"<!--section=description-->\n<p>RestorePilot Backup &amp; Migration is a straightforward backup and restore plugin for WordPress site owners, developers, and small agencies.<\/p>\n\n<p>It creates a downloadable backup package containing this site's WordPress database tables and, optionally, the <code>wp-content<\/code> 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 \u2014 no manual search-and-replace needed.<\/p>\n\n<h4>Why RestorePilot<\/h4>\n\n<p>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.<\/p>\n\n<ul>\n<li><strong>A rollback point before every restore.<\/strong> RestorePilot saves your current database before it changes anything, and you can restore straight from it if something goes wrong \u2014 no separate backup step, no remembering to do it yourself.<\/li>\n<li><strong>Resumes instead of restarting.<\/strong> A host timeout, a closed browser tab, a slow connection \u2014 a backup or restore picks up from exactly where it stopped, including partway through a single large database table, instead of starting the whole thing over.<\/li>\n<li><strong>No size ceiling.<\/strong> Large sites are split into volumes automatically, so a host's per-file size limit stops being a reason a backup can fail.<\/li>\n<li><strong>Nothing leaves your server.<\/strong> Backups are written to your own WordPress uploads directory. RestorePilot has no cloud storage integration and sends nothing to the plugin author or any third party \u2014 see Privacy &amp; data below.<\/li>\n<li><strong>Built for migration, not just backup.<\/strong> Source and target URLs are detected automatically from the backup itself, with serialized-safe replacement across options, widgets, and post meta \u2014 restoring a backup on a different domain does not need a manual search-and-replace pass.<\/li>\n<\/ul>\n\n<h4>Features<\/h4>\n\n<p><strong>Backup<\/strong><\/p>\n\n<ul>\n<li>Full site backup: database + wp-content files.<\/li>\n<li>No size limit: backups are split into volumes, so a site is limited by free disk space rather than by how large a single file the server allows.<\/li>\n<li>Constant memory use: the database is exported and restored as a stream, so database size is not limited by PHP's memory limit.<\/li>\n<li>Resumes automatically: if a background backup is interrupted by a host timeout, it continues from where it left off on the next attempt instead of starting over.<\/li>\n<li>One-click full backup download for restore or migration.<\/li>\n<li>Advanced file selection: choose which top-level wp-content folders to include.<\/li>\n<li>Friendly backup filenames with site name and date\/time.<\/li>\n<li>Background backup jobs \u2014 navigating away does not cancel the backup.<\/li>\n<li>Progress bar with percent complete and estimated time remaining.<\/li>\n<li>Cancel button for running backups.<\/li>\n<li>Health check before restore to verify backup integrity.<\/li>\n<li>Free version keeps the newest 2 backups total across manual and daily backups.<\/li>\n<\/ul>\n\n<p><strong>Restore &amp; Migrate<\/strong><\/p>\n\n<ul>\n<li>Restore from an uploaded backup zip.<\/li>\n<li>Large uploads are sent in smaller chunks to bypass PHP upload limits.<\/li>\n<li>Restore from a zip already inside the site's uploads directory (useful for very large sites).<\/li>\n<li>Auto-detect source and target URLs from the backup manifest.<\/li>\n<li>Manual source\/target URL mode for advanced migrations.<\/li>\n<li>Serialized-safe URL replacement (handles WordPress options, widgets, post meta).<\/li>\n<li>Table prefix mapping between source and target sites.<\/li>\n<li>Pre-restore database rollback point for safety.<\/li>\n<li>Resumes automatically: if a background restore is interrupted by a host timeout, it continues from where it left off \u2014 including partway through a large table \u2014 on the next attempt instead of starting over.<\/li>\n<li>Atomic table swap: new tables are staged before replacing live ones.<\/li>\n<li>Maintenance mode during restore, automatically removed on completion or failure.<\/li>\n<li>Post-restore success dialog after login.<\/li>\n<li>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.<\/li>\n<\/ul>\n\n<p><strong>Downloads<\/strong><\/p>\n\n<ul>\n<li>Full backup zip is the primary download for restore and migration.<\/li>\n<li>Advanced downloads for database, plugins, themes, uploads, must-use plugins, and other wp-content files.<\/li>\n<li>Large backups are handed off to the web server where possible.<\/li>\n<li>Resumable PHP streaming with HTTP Range support as a fallback.<\/li>\n<\/ul>\n\n<p><strong>Scheduled backups &amp; notifications<\/strong><\/p>\n\n<ul>\n<li>Optional daily automatic backups via WP-Cron from the Daily Backup tab.<\/li>\n<li>Optional email notification after backup success or failure.<\/li>\n<\/ul>\n\n<p><strong>Logs &amp; diagnostics<\/strong><\/p>\n\n<ul>\n<li>Logs tab with refresh, download, clear, and quick filters.<\/li>\n<li>Dark-themed log viewer for easy reading.<\/li>\n<li>Database-backed fallback log if file logging fails.<\/li>\n<li>System Readiness panel: PHP version, ZIP support, disk space, backup folder, WP-Cron.<\/li>\n<li>Diagnostics &amp; Maintenance panel for backup storage status, temp cleanup, stuck runtime reset, and log tools.<\/li>\n<li>Runtime PHP warning and fatal error logging during RestorePilot actions.<\/li>\n<\/ul>\n\n<p><strong>WP-CLI<\/strong><\/p>\n\n<ul>\n<li><code>wp restorepilot backup<\/code> \u2014 create a full backup.<\/li>\n<li><code>wp restorepilot backup --db-only<\/code> \u2014 database-only backup.<\/li>\n<li><code>wp restorepilot health<\/code> \u2014 check the newest backup.<\/li>\n<\/ul>\n\n<p><strong>Security &amp; compatibility<\/strong><\/p>\n\n<ul>\n<li>Admin-only access with nonce verification on every action.<\/li>\n<li>Backup storage protected by <code>.htaccess<\/code> and <code>index.php<\/code>.<\/li>\n<li>Randomised backup filenames to reduce direct-access risk.<\/li>\n<li>Installed backup plugins (UpdraftPlus, Duplicator, WP Staging, etc.) are\nbacked up normally; only their <em>stored backup archives<\/em> are excluded from\nRestorePilot backups to avoid backup-of-backups bloat.<\/li>\n<li>Missing active plugin references are cleaned after restore to avoid WordPress\ndeactivating unavailable plugins with a scary admin notice.<\/li>\n<li>Full cleanup on uninstall: backups, logs, temp files, options, scheduled events.<\/li>\n<li>Multisite compatible uninstall. Note: creating backups and running restores is not supported on multisite networks.<\/li>\n<\/ul>\n\n<h4>Important note<\/h4>\n\n<p>This is an early release. Always test restores on a staging site before using RestorePilot on a production site.<\/p>\n\n<h4>Privacy &amp; data<\/h4>\n\n<p>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 inside the WordPress uploads directory unless you manually download or move them elsewhere. RestorePilot does not send backup data to the plugin author or to any third-party service.<\/p>\n\n<!--section=installation-->\n<h4>From your WordPress admin (most common)<\/h4>\n\n<ol>\n<li>Go to <strong>Plugins \u2192 Add New Plugin<\/strong>.<\/li>\n<li>Search for \"RestorePilot\".<\/li>\n<li>Click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<li>Go to <strong>RestorePilot<\/strong> in the admin menu and create your first backup.<\/li>\n<\/ol>\n\n<h4>Manual install (if you downloaded the zip separately)<\/h4>\n\n<ol>\n<li>Upload the <code>restorepilot-backup-migration<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or upload the zip directly via <strong>Plugins \u2192 Add New Plugin \u2192 Upload Plugin<\/strong>.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen.<\/li>\n<li>Go to <strong>RestorePilot<\/strong> in the admin menu and create your first backup.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20restorepilot%20support%20migrations%20to%20a%20different%20domain%3F\"><h3>Does RestorePilot support migrations to a different domain?<\/h3><\/dt>\n<dd><p>Yes. RestorePilot stores the source site URL in the backup manifest and replaces it with the current site URL during restore \u2014 automatically.<\/p><\/dd>\n<dt id=\"do%20i%20need%20to%20enter%20old%20and%20new%20urls%20manually%3F\"><h3>Do I need to enter old and new URLs manually?<\/h3><\/dt>\n<dd><p>No. Auto-detect is on by default. Manual URL fields are available in Advanced restore settings for edge cases.<\/p><\/dd>\n<dt id=\"does%20it%20handle%20serialized%20wordpress%20data%3F\"><h3>Does it handle serialized WordPress data?<\/h3><\/dt>\n<dd><p>Yes. URL replacement is applied after unserializing values where possible, then the values are serialized again. Incomplete PHP classes are safely skipped.<\/p><\/dd>\n<dt id=\"where%20are%20backups%20stored%3F\"><h3>Where are backups stored?<\/h3><\/dt>\n<dd><p>Under the WordPress uploads directory in a protected <code>restorepilot-backup-migration<\/code> folder. The folder is excluded from future RestorePilot backups.<\/p><\/dd>\n<dt id=\"are%20other%20backup%20plugins%27%20files%20excluded%20from%20the%20backup%3F\"><h3>Are other backup plugins' files excluded from the backup?<\/h3><\/dt>\n<dd><p>RestorePilot excludes the <em>backup archives<\/em> created by other plugins (UpdraftPlus, Duplicator, BackupBuddy, WP Staging, etc.) to avoid including huge backup zips inside your backup. The backup plugins <em>themselves<\/em> (their code inside <code>wp-content\/plugins\/<\/code>) are included normally.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20delete%20the%20plugin%3F\"><h3>What happens when I delete the plugin?<\/h3><\/dt>\n<dd><p>Deleting the plugin removes all RestorePilot backups, logs, temporary download files, background job data, backup locks, and scheduled events.<\/p><\/dd>\n<dt id=\"my%20backup%20is%20larger%20than%20the%20browser%20upload%20limit.%20what%20do%20i%20do%3F\"><h3>My backup is larger than the browser upload limit. What do I do?<\/h3><\/dt>\n<dd><p>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 <strong>Advanced restore settings \u2192 Server backup path<\/strong> during restore.<\/p><\/dd>\n<dt id=\"why%20is%20my%20backup%20split%20into%20several%20files%3F\"><h3>Why is my backup split into several files?<\/h3><\/dt>\n<dd><p>Many hosts refuse to create a file beyond a fixed size \u2014 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: <code>your-backup.zip<\/code>, <code>your-backup-v002.zip<\/code>, and so on. A small site produces a single file and looks exactly as before.<\/p>\n\n<p>Keep the whole set together. To restore, place every volume in the same folder \u2014 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 <code>restorepilot_backup_volume_bytes<\/code> filter.<\/p>\n\n<p>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 \u2014 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.<\/p><\/dd>\n<dt id=\"my%20backup%20or%20restore%20shows%20%22continuing%20in%20the%20background%22%20instead%20of%20finishing%20right%20away%20%E2%80%94%20is%20that%20normal%3F\"><h3>My backup or restore shows \"continuing in the background\" instead of finishing right away \u2014 is that normal?<\/h3><\/dt>\n<dd><p>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 cannot lose progress \u2014 the next chunk simply continues from exactly 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. A scheduled (cron) daily backup is unaffected and still runs as a single process.<\/p><\/dd>\n<dt id=\"can%20i%20check%20a%20backup%20before%20restoring%3F\"><h3>Can I check a backup before restoring?<\/h3><\/dt>\n<dd><p>Yes. Click <strong>Health Check<\/strong> next to any backup. RestorePilot verifies the zip structure, manifest, database export, and file paths.<\/p><\/dd>\n<dt id=\"how%20many%20backups%20does%20restorepilot%20keep%3F\"><h3>How many backups does RestorePilot keep?<\/h3><\/dt>\n<dd><p>The free version keeps the newest 2 backups total. Manual backups and daily automatic backups share the same limit; older backups are removed automatically.<\/p><\/dd>\n<dt id=\"can%20i%20run%20backups%20from%20wp-cli%3F\"><h3>Can I run backups from WP-CLI?<\/h3><\/dt>\n<dd><p>Yes. Use <code>wp restorepilot backup<\/code> for a full backup, <code>wp restorepilot backup --db-only<\/code> for database only, and <code>wp restorepilot health<\/code> to check the newest backup.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20a%20restore%20fails%3F\"><h3>What happens if a restore fails?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.5.0<\/h4>\n\n<ul>\n<li>Added: backups now split into volumes of up to 1 GB instead of one large file, so hosts with a per-file size limit can back up large sites. Total backup size is limited only by available disk space. Configurable via the <code>restorepilot_backup_volume_bytes<\/code> filter.<\/li>\n<li>Added: background backups and restores now run in short, resumable chunks instead of one continuous process, picking up automatically if a host interrupts them partway through \u2014 no restart from zero.<\/li>\n<li>Added: the database is exported and restored as a stream instead of being loaded into memory, so backup and restore are limited by disk space rather than PHP's memory limit.<\/li>\n<li>Added: an optional \"Create a new admin login for this site\" restore option adds a brand-new administrator account without touching any existing one \u2014 useful when restoring a backup to a different domain whose admin credentials you don't have. The generated password is shown once, right after the restore completes.<\/li>\n<li>Added: if a restore stops responding, signed-in administrators now see its real progress instead of a blank maintenance page, with a one-click way to end it and unlock the site \u2014 instead of waiting up to two hours.<\/li>\n<li>Improved: the progress bar now moves steadily through the database stage instead of stopping on one number for the whole of it, and names the table it has reached (\"36% done \u2022 Exporting database (table 47 of 149)\"). On a site with a lot of database tables that stage can run for several minutes, and a bar that never moved was impossible to tell apart from a backup that had died.<\/li>\n<li>Fixed: the backup progress display could make a perfectly healthy backup look broken. The percentage could jump backwards (8%, then 0%, then 30%) because a page reload or a resumed step reported a lower figure; the heading kept saying \"Backup in progress\" after a backup had been canceled or had already finished; and a single failed status check \u2014 a dropped request, a moment of server load \u2014 permanently stopped the page watching a backup that was still running, leaving the finished backup invisible until the page was reloaded by hand. Progress now only moves forward, the heading follows the real state, and a failed status check is retried instead of being treated as a failed backup.<\/li>\n<li>Changed: the backup progress line now shows which stage is running and how long it has been going (\"8% done \u2022 Exporting database \u2022 1m 12s elapsed\") instead of guessing the seconds remaining. The old estimate assumed every stage ran at the same speed, which they do not \u2014 exporting a database of many small tables is far slower per percent than collecting files \u2014 so it was often wrong and could even count upwards. Naming the stage also helps most in the moment it matters: a backup sitting at 8% for a minute looks stuck until it says it is exporting the database.<\/li>\n<li>Fixed: the stored-backups notice read \"You currently have 1 backups stored\", because a single plural rule was being applied to two different numbers in the same sentence.<\/li>\n<li>Fixed: the pre-restore rollback point \u2014 the safety net every restore creates automatically \u2014 could not actually be restored. It's now the one thing that reliably works when a restore needs to be undone.<\/li>\n<li>Fixed: restoring from a rollback point could delete the very file it was restoring from, if that file happened to be the oldest one kept. The file being restored from is now always protected from cleanup.<\/li>\n<li>Fixed: a restore of a site with many plugins could crash partway through and leave the site down, because the database was replaced before the corresponding plugin files had been restored. Plugins are now safely held back until every file is back in place, then switched on automatically.<\/li>\n<li>Fixed: \"Download Full Backup\" on a backup split into volumes only ever delivered the first volume, though the button showed the full, correct size. It now always delivers one complete file; individual volumes remain available separately for retrying a failed download.<\/li>\n<li>Fixed: a combined multi-volume download couldn't be restored \u2014 it still reported its original volume count, so a restore rejected it as incomplete even though it was whole.<\/li>\n<li>Fixed: Advanced downloads (database\/plugins\/themes\/uploads only) on a multi-volume backup only ever looked in the first volume, silently omitting content stored in later ones.<\/li>\n<li>Fixed: Master Reset's \"wipe all uploads\" step deleted RestorePilot's own stored backups, rollback points, and log along with everything else \u2014 including a backup manually placed there for the Server backup path option. RestorePilot's own storage is now excluded, as intended.<\/li>\n<li>Security: a database column containing raw binary data (for example an IP-address column) could be silently corrupted during backup due to a detection bug, occasionally causing two different rows to collide and making a later restore fail with a duplicate-key error. Binary data is now preserved byte-for-byte. A backup taken before this fix should be retaken.<\/li>\n<li>Security: a restore now rejects a table-creation statement that isn't a plain table definition, closing a path where a crafted backup archive could smuggle in a query that copies existing site data into a new table.<\/li>\n<li>Security: serialized values inside a backup can no longer instantiate PHP classes during URL replacement.<\/li>\n<li>Fixed: once a restore turned on maintenance mode, the requests it depends on to continue (its own background dispatch) were blocked by that same maintenance mode, permanently stalling the restore with no error shown. Maintenance mode is now enforced by RestorePilot itself so it can let its own traffic through.<\/li>\n<li>Fixed: canceling a backup could let a second backup start while the first was still finishing its current step; locks are now released only once the first has actually stopped.<\/li>\n<li>Fixed: a restore now fully validates the backup's database export \u2014 structure, required tables, row shapes \u2014 before making any change, instead of discovering a problem partway through.<\/li>\n<li>Fixed: database export now reads every table in a fixed, consistent order, so rows can no longer be duplicated or skipped if site content changes while a backup is running.<\/li>\n<li>Fixed: a failed chunked-upload reassembly left every already-uploaded piece on disk instead of cleaning up, and could briefly need nearly double the backup's size in free space; both are now handled correctly, and a doomed attempt fails immediately with a clear \"space available vs. needed\" message.<\/li>\n<li>Fixed: an interrupted restore's temporary database tables were not excluded from later backups, so a subsequent backup could include them as if they were real site content.<\/li>\n<li>Fixed: resuming a restore with many already-restored rows to skip past had no time budget for that step, so it could run far longer than one chunk should with nothing saved if interrupted. Skipping now yields cooperatively like the rest of a restore chunk.<\/li>\n<li>Fixed: on multisite, backup and restore are now refused immediately with a plain explanation, instead of after files were already uploaded or jobs already queued. Backup, restore, and Master Reset remain unavailable on multisite, where plugins, themes, and shared core tables span the whole network.<\/li>\n<li>Fixed: a full backup no longer silently excludes files based on their extension (for example a stray <code>.zip<\/code> file in wp-content), which could have omitted legitimate content while still reporting success.<\/li>\n<li>Fixed: Master Reset refuses to run on a site using a custom shared user table, instead of deleting from a table that may belong to a different WordPress installation.<\/li>\n<li>Fixed: restore no longer removes leftover staging tables by a loose wildcard match, which could have dropped an unrelated table sharing the same naming pattern; only tables it created itself are ever removed.<\/li>\n<li>Fixed: after Master Reset, the active theme and the <code>home<\/code> option could each be left in a broken state; both are now handled correctly.<\/li>\n<li>Fixed: three restore-lock recovery paths could leave a stale per-chunk lock behind, or briefly open a window where a second restore could start; all recovery paths now release both locks cleanly.<\/li>\n<li>Fixed: a rollback point split across multiple volumes was counted and pruned as several separate points instead of one, which could leave orphaned volume files behind after cleanup.<\/li>\n<li>Fixed: a WordPress core issue in some versions silently breaks <code>%<\/code>-containing values passed through <code>$wpdb-&gt;prepare()<\/code>, which could prevent this plugin's own leftover lock and job cleanup from finding what it needed to remove.<\/li>\n<li>Improved: write failures during backup or restore now report the operating system's reason, how much had been written, and free space at that moment, and distinguish a full disk from an invisible hosting quota.<\/li>\n<li>Changed: every database identifier is now passed through <code>$wpdb-&gt;prepare()<\/code>'s <code>%i<\/code> placeholder rather than manual escaping, which raises the minimum required WordPress version to 6.2.<\/li>\n<li>Changed: when a third-party maintenance page already exists, RestorePilot no longer touches it; the site still enters maintenance via WordPress's own mechanism.<\/li>\n<\/ul>\n\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>Added: per-entry ZIP64 support \u2014 backups containing individual files larger than 4 GB no longer fail.<\/li>\n<li>Added: loopback HTTP dispatch for background restore jobs, so restores continue when WP-Cron is disabled or the browser tab closes.<\/li>\n<li>Added: \"Restore from rollback\" panel in the Restore tab \u2014 pre-restore rollback points are now listed with a one-click restore button.<\/li>\n<li>Added: \"Settings\" quick link in the Plugins list and a Support link in the plugin row meta.<\/li>\n<li>Fixed: serialized scalar values (integers, booleans, floats) were silently corrupted during URL replacement when the value looked serialized but contained no URL.<\/li>\n<li>Fixed: block-editor JSON with escaped forward slashes (<code>https:\\\/\\\/<\/code>) was missed during URL replacement after migration.<\/li>\n<li>Fixed: background restore job had no loopback worker endpoint \u2014 the restore worker now runs reliably without an active browser session.<\/li>\n<li>Fixed: creating a backup with the advanced file selection panel open (even with all folders selected) incorrectly tagged the backup as \"Partial\" instead of \"Full\". Backups are now labelled \"Partial\" only when the user has explicitly excluded at least one folder.<\/li>\n<li>Fixed: stale <code>rp_tmp_<\/code> and <code>rp_old_<\/code> tables left by an interrupted restore were not cleaned up before the next restore run.<\/li>\n<li>Fixed: pre-restore <code>CREATE TABLE<\/code> statements were not validated, allowing a malformed backup to inject arbitrary SQL.<\/li>\n<li>Fixed: cron-based backup and restore workers did not register the shutdown handler, so a fatal error during WP-Cron could leave maintenance mode permanently enabled.<\/li>\n<li>Fixed: partial-zip temp files were not cleaned up when <code>addFile()<\/code> threw an exception.<\/li>\n<li>Fixed: worker lock acquisition had a TOCTOU race that could allow two workers to run simultaneously for the same job.<\/li>\n<li>Fixed: long single-table database restores (&gt; 2 h) could trigger the stale-job detector and release an active lock.<\/li>\n<li>Improved: admin CSS and JavaScript are now properly enqueued via <code>wp_enqueue_style<\/code> \/ <code>wp_enqueue_script<\/code> instead of being inlined in the page output.<\/li>\n<\/ul>\n\n<h4>0.3.1<\/h4>\n\n<ul>\n<li>Added a Daily Backup tab with daily automatic backup settings and an existing backups section.<\/li>\n<li>Added one-click full backup downloads, with database\/plugins\/themes\/uploads downloads moved into Advanced downloads.<\/li>\n<li>Changed free-version retention to keep the newest 2 backups total across manual and daily backups.<\/li>\n<li>Added a Settings diagnostics and maintenance panel with backup storage status, stale temp cleanup, stuck runtime reset, and log tools.<\/li>\n<li>Hardened restore safety by validating target URLs, limiting server-path restores to the site's uploads directory, and skipping non-WordPress-prefix tables.<\/li>\n<li>Improved backup storage privacy by adding random suffixes to new backup and rollback filenames.<\/li>\n<li>Fixed: selected top-level folder backups now pass full wp-content-relative paths to the exclusion matcher, so <code>plugins\/updraftplus<\/code>, <code>plugins\/duplicator<\/code>, and similar plugin code folders are included correctly.<\/li>\n<li>Fixed: after restore, missing active plugin references are removed cleanly and logged, preventing WordPress from showing \u201cplugin file does not exist\u201d notices for old incomplete backups.<\/li>\n<\/ul>\n\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>Fixed: installed backup plugins (UpdraftPlus, Duplicator, WP Staging, etc.) were incorrectly excluded from backups due to an interior path-match bug. Only their stored backup archives are now excluded.<\/li>\n<li>Fixed: URL replacement used a bare domain match (<code>old.com<\/code>) that could corrupt email addresses and sibling domain names. Replacement now only matches full scheme-prefixed URLs (<code>https:\/\/<\/code>, <code>http:\/\/<\/code>, <code>\/\/<\/code>).<\/li>\n<li>Fixed: database columns containing non-UTF-8 binary data caused a backup failure. Binary values are now base64-encoded in the export and decoded transparently on restore.<\/li>\n<li>Fixed: progress bar regressed from 95% to 92% for large backups after zip finalization. Progress now increases monotonically.<\/li>\n<li>Fixed: <code>add_directory_to_zip<\/code> used <code>str_replace($dir, $path)<\/code> which could strip the directory name multiple times. Replaced with <code>substr<\/code>.<\/li>\n<li>Fixed: <code>force_release_backup_locks<\/code> checked stale status using the lock start time instead of the job's last-updated time, which could release locks on long-running but active backups.<\/li>\n<li>Fixed: WP-CLI commands were registered at file-load time instead of the <code>cli_init<\/code> hook.<\/li>\n<li>Fixed: <code>enforce_backup_retention()<\/code> was called during restore when no new backup had been created.<\/li>\n<li>Fixed: generic <code>backup-<\/code> and <code>backup_<\/code> folder prefix rules in the skip list could exclude legitimate plugins and themes named with those prefixes.<\/li>\n<li>Fixed: <code>.gz<\/code> extension in the skip list excluded pre-compressed asset files. Now only <code>.sql.gz<\/code> and <code>.tar.gz<\/code> are excluded.<\/li>\n<li>Improved: <code>should_skip_file()<\/code> now pre-compiles lookup tables once per PHP process, reducing string comparisons by ~60% on large file sets.<\/li>\n<li>Improved: replaced private WordPress function <code>_get_cron_array()<\/code> with the public <code>wp_clear_scheduled_hook()<\/code> API (safe since WordPress 5.1).<\/li>\n<li>Improved: redesigned admin UI \u2014 branded page header, tab icons, card layout, dark log viewer, color-coded system status, better modals and forms.<\/li>\n<li>Updated: version bump to 0.3.0 to reflect the scope of fixes and improvements.<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Added separate Backup, Restore, Logs, and Settings tabs.<\/li>\n<li>Added friendlier backup filenames.<\/li>\n<li>Added configurable backup retention setting.<\/li>\n<li>Added log refresh, download, clear, and quick filters.<\/li>\n<li>Added system readiness panel in Settings.<\/li>\n<li>Added post-restore checklist after successful restores.<\/li>\n<li>Added clearer pre-restore modal and post-login success dialog.<\/li>\n<li>Moved restore rollback points into separate hidden storage so they do not appear as normal backups.<\/li>\n<li>Added backup health checks.<\/li>\n<li>Added restore preflight validation before maintenance mode starts.<\/li>\n<li>Added streaming file restore to reduce memory pressure.<\/li>\n<li>Added chunked large-file restore uploads for easier browser-based restores.<\/li>\n<li>Added pre-restore database rollback point.<\/li>\n<li>Added optional server-path restore for backups already on the server.<\/li>\n<li>Added optional daily scheduled backups.<\/li>\n<li>Added optional email notifications after backup success or failure.<\/li>\n<li>Added WP-CLI backup and health-check commands.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Initial public release.<\/li>\n<\/ul>","raw_excerpt":"Back up, restore, and migrate WordPress sites with automatic URL detection and serialized-safe replacement.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/332373","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=332373"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/srjdev"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=332373"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=332373"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=332373"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=332373"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=332373"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=332373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}