BackupRidge

Changelog

1.29.0

Major update: redesigned incremental backups, Advanced push migration & staging, safer restores, and license/security hardening.

  • New (Advanced): Direct push migration & staging — push a full site to another WordPress install with pre-flight checks, chunked resumable transfer, automatic URL search-replace, and a post-migration health check. Staging mode clones to a staging target behind a typed production-push confirmation.
  • New (Advanced): Incremental backups now use a differential model (delta since the last full/baseline) instead of a forward chain. A restore needs only two archives — the baseline plus the chosen differential — removing the old dependency on an unbroken chain of every prior run.
  • New: Each archive now embeds a self-describing file manifest (paths, hashes, baseline reference), so restores are deletion-correct and portable — an archive can be restored on a new site, or after a license lapse, without depending on stored site state. Restore remains a Standard feature.
  • New: Backup history now labels each backup as Full or Differential so you can identify the baseline at a glance.
  • Fix: Restoring a standalone differential without its baseline is now blocked with a clear explanation instead of silently producing an incomplete site.
  • Fix: Retention never prunes a baseline that a later differential still depends on, and manually deleting a depended-on baseline now requires confirmation.
  • Fix: Incremental change detection compares file size alongside modification time, so content changes that preserve the original mtime are no longer skipped. Incremental backups also re-baseline automatically on a configurable cadence.
  • New: Site migration now performs serialization-safe search-replace across plugin tables (not only core WordPress tables) on the destination.
  • Security: Hardened the migration chunk assembler against path traversal via unvalidated identifiers, confining all archive writes and deletes to the migration work area.
  • Security (Advanced): License plan tiers are now enforced, so a Personal license no longer unlocks Business-tier features. License validation adds a 14-day offline grace period so a license-server outage no longer disables Advanced features for paying customers, sends a site-ownership proof on license detail and transfer calls, and includes the license key when connecting cloud storage via Quick Connect.
  • Change: Clearer upgrade information — accurate plan names and pricing on the in-plugin upgrade screens, and the readme now documents site migration and the WP-Cron vs. system-cron scheduling split.
  • Fix: On a slow or contended host, a batch of many small files during file backup could go long enough without a heartbeat that a background watchdog started a duplicate resumption while the original was still running, silently dropping archive entries while the backup still reported success. The heartbeat now refreshes throughout the batch, not only once it finishes.
  • Fix: Uninstalling no longer leaves job-scheduled cron events behind.
  • Fix: Removed the “use custom database tables” setting, which never had a backing implementation.

1.28.8

  • Fix: On a Advanced install, the “Go Advanced” upgrade link in the page header kept showing even after successfully activating a license, and the header never showed a badge for the active plan. Advanced now shows an “Activate License” prompt only while unlicensed, and the plan’s badge once a license is active.

1.28.7

  • Fix: During restore, a brief window existed where a concurrent status check could see the source backup’s job as still “running” and start it again, overwriting the backup archive while it was being restored from. Restore now holds the source job’s lock for its full duration so this can’t happen.
  • Fix: A backup restored from a mysqldump-based export could resurrect and re-run its own source backup job, overwriting the original archive, because the exported database dump included the plugin’s own in-progress job data. Database exports now exclude this data, matching the existing PHP-export path.
  • Fix: A backup could run twice in a row and duplicate its database dump in the archive when two internal triggers (e.g. a manual start and a scheduled resumption check) raced to start the same job within the same second. The second trigger now always sees the job’s true up-to-date status instead of a stale cached copy.
  • Fix: Large-file backups could produce an oversized archive part exceeding the configured maximum size; the flush threshold is now capped by the space actually remaining in the current part.
  • Fix: Restores could appear frozen for 20+ seconds on modern hosts due to an overly conservative pause between each database table; the pause is now much shorter while remaining safe for older MySQL versions.
  • Fix: Backup log filenames now consistently match their corresponding archive filenames.
  • Change: Removed the plugin’s custom dark-mode styling, which only recolored the plugin’s own content area and looked inconsistent with the rest of the WordPress admin.

1.28.6

  • Fix: On slow hosts, a large backup could log “completed successfully” while actually storing nothing — the finished archive was lost when a background watchdog restarted the job during the final archive step (embedding the database and closing the archive). That final step is now reliable: it keeps the job alive while it runs, resumes correctly if interrupted, and — as a safety net — the backup now fails with a clear error instead of reporting success when no archive was produced. If you run large backups on a slow host, please run a fresh backup and confirm it completes with archives present.
  • Change: Per-component backup log lines now report each component’s full file count instead of only the files added in the final resumption segment, so the log accurately reflects how much was archived.

1.28.5

  • Fix: Backups containing a few very large files now split into properly-sized parts instead of one oversized part that could far exceed the configured maximum (and be rejected by storage providers with a per-file size limit). The time limit is also checked while those large files are added, so backups still pause and resume in time on slow hosts.
  • Change: Clearer backup logs — a missing optional mu-plugins directory is now logged as informational rather than an error, and a remote upload that continues across requests logs “Resuming provider” instead of “Starting provider”.

1.28.4

  • Fix: When a backup moves many large archive parts into local storage on a slow host, it now pauses and resumes cleanly between parts instead of risking a timeout part-way through the transfer.
  • Change: Clarified the “Resumption attempts” setting — it is now labelled a soft limit, with help text explaining that it never fails a backup on its own (a genuinely stuck backup is stopped automatically by stall detection).

1.28.3

  • Fix: On hosts that allow longer PHP execution, backups now run in fewer, longer segments instead of restarting roughly every 90 seconds. This cuts resumption overhead and the number of background hand-offs on large sites; total backup time is unchanged on restrictive hosts.
  • Fix: A backup that stops making progress is now detected and stopped with a clear error after several idle resumptions, instead of resuming indefinitely. This closes a gap where a stuck database-export or upload phase could loop forever.
  • Fix: Split archive parts no longer exceed the configured maximum part size. Previously a single batch of files could push a part well over the limit, which could cause a remote destination with a hard per-part size limit to reject the upload.
  • Change: The backup log is more diagnostic. It now warns (with the specific reason) when the slower pure-PHP archive method is used, and lists the largest subdirectories by file count in each component, making it easier to spot and exclude caches or other bloat that slow backups down.

1.28.2

  • Change: Backup downloads now run through WordPress’s standard request handling instead of a separate download script. This improves compatibility with hosts that block direct PHP execution under the uploads directory. Existing download links keep working; no action is required.
  • Security: Removed all directly-accessible standalone PHP files from the plugin and stopped writing any PHP into the uploads directory.

1.28.1

  • Fix: Dropbox uploads failed with a “not_found” error because the upload session id was parsed incorrectly, and files were written to a doubled “/backups/backups/” path. Both are resolved.
  • Fix: OneDrive and Google Drive uploads now send the correct total file size in the Content-Range header, so OneDrive no longer rejects chunks and Google Drive reliably finalizes the uploaded file.
  • Fix: Backblaze B2 uploads now stream large archives via the B2 large-file API instead of loading the whole file into memory, eliminating out-of-memory fatals on large backups.
  • Fix: Each remote destination now keeps its own resumable-upload checkpoint, preventing one provider from reusing another provider’s in-progress upload when the same archive is sent to multiple destinations.
  • Fix: A backup destination that exhausts its retries is now recorded and skipped on later resumptions, so an unreachable destination can no longer loop a backup indefinitely; the backup completes with warnings instead.
  • Fix: Resuming between destinations now advances the resumption counter correctly, preventing duplicate work and intermittent upload errors during multi-destination backups.

1.28.0

  • New: S3 and Cloudflare R2 destinations now include a cleanup tool to list and abort orphaned incomplete multipart uploads left behind by interrupted backups. AWS and R2 charge for stored parts until they are explicitly aborted; the new admin endpoints expose this via the storage settings page.
  • Fix: Google Drive, Dropbox, and OneDrive uploads now stream archive data in chunks instead of loading the entire file into memory, eliminating out-of-memory fatals when uploading large archives. Google Drive additionally recovers the server-side byte offset on WP-Cron resumption so interrupted uploads continue cleanly.
  • Fix: Out-of-memory fatals during the upload phase now show a specific message advising users to reduce the maximum archive size (Settings → Archive) rather than the generic batch-size message, which does not apply to upload memory usage.
  • Fix: Eleven upload pipeline stability fixes: multipart upload abort on failure, per-provider retry budget enforcement, resumption slice guard to prevent starvation, progress stall detection, and more.

1.27.1

  • Fix: Resolved an infinite resumption loop during the upload phase when resumption_slice_seconds is configured and one or more remote providers fail before an S3/R2 destination. The per-provider retry delay could exhaust the execution slice budget, causing the S3 chunked upload to yield immediately on every segment without sending any data. The retry delay now yields the slice instead of blocking when the deadline is approaching. Additionally, already-completed provider uploads are now preserved across resumption segments so they are not re-run unnecessarily.

1.27.0

  • New: Upload failures are now logged per provider and recorded in job history. Jobs that succeed to at least one destination (but fail others) complete with a “Complete with Warnings” status and a yellow badge, keeping them restorable while surfacing the partial failure.
  • New: Storage providers that fail a connection test are marked “Unavailable” and disabled as backup destinations until re-tested — preventing silent backup omissions.
  • New: If the site’s encryption key has changed since credentials were last saved, affected providers are flagged with a “Key mismatch” badge and disabled until credentials are re-entered. An admin notice lists the affected providers and links to the storage settings page.
  • New: OAuth providers (Google Drive, OneDrive, Dropbox) now run an automatic connection test immediately after authorization redirect, so any permission or scope issue surfaces instantly.
  • New: Configurable per-provider upload retry: if an upload to a provider fails after all chunk-level retries are exhausted, BackupRidge retries the entire provider upload up to N times (default: 2) with a configurable delay (default: 30 s). If all retries fail, the provider is marked unavailable. Configure under Settings → Upload.
  • Improved: AjaxHandler refactored into nine focused handler classes, reducing the largest file from ~5,200 to ~460 lines and making the codebase easier to audit.
  • Improved: Reviewer-parity error count reduced from 230 to 45 (structural floor — remaining items are genuine WordPress coding standards edge cases with inline justifications).

1.26.2

  • Fixed: Plugin Check gate now correctly handles the per-file output format introduced in Plugin Check 1.9.0, preventing findings from being silently missed.
  • Fixed: Applied esc_sql() to the migration preflight test table name in HandshakeValidator to satisfy Plugin Check 1.9.0’s new database parameter check.
  • Improved: Replaced string interpolation with concatenation in SearchReplace queries to remain compatible with Plugin Check’s annotation-stripping PHPCS mode.
  • Improved: Suppression baseline lowered from 16 to 14 (two now-unnecessary suppressions removed).

1.26.1

  • Fixed: Removed unnecessary ini_set(‘memory_limit’) fallback — wp_raise_memory_limit() is always available on supported WordPress versions.
  • Fixed: Replaced strip_tags() with wp_strip_all_tags() per WordPress coding standards.
  • Improved: Added inline code comments explaining SQL identifier escaping, dynamic IN() list patterns, cron interval necessity, base64 encoding usage, and standalone download gateway patterns — making the codebase easier to audit and reducing false-positive flags during WordPress review.
  • Improved: Log file download now applies wp_strip_all_tags() before output.
  • Improved: Input sanitization applied at the point of read for array parameters in AJAX handlers.

1.26.0

Security release — please review the cron note below if you use system cron.

  • Important: The system-cron trigger now authenticates with an HTTP header (X-BackupRidge-Cron-Key) instead of a key in the URL, so the secret no longer leaks into server access logs or Referer headers. If you run BackupRidge from a system cron job, update it to the new command shown on the Settings page — the old ?key= URL will now return 403. To keep using the URL-key method, add define( ‘BACKUPRIDGE_ALLOW_CRON_QUERY_KEY’, true ); to wp-config.php.
  • Security: Backup archives and logs are now protected against direct web access with deny rules and an unguessable token in each filename.
  • Security: Blocked PHP object injection during restore search-and-replace.
  • Security: Test-only scaffolding AJAX handlers are no longer registered in production builds.
  • Security: The standalone download endpoint is now confined to the backup directory (path-traversal hardening).
  • Security: Backup downloads now send Referrer-Policy and X-Robots-Tag: noindex headers.
  • Security: Database identifiers are escaped through a single helper and ID lists use prepared statements.
  • Changed: On multisite, backup, restore, storage, and migration actions now require a network super-admin.
  • Changed: Documentation clarifies that archive encryption uses AES-256-GCM authenticated encryption (legacy AES-256-CBC archives remain decryptable for restore).

For the complete version history, see the plugin’s SVN changelog.

Plugin Website
Visit website

Author
stavatech
Version:
1.29.0
Last Updated
July 8, 2026
Requires
WordPress 6.7
Tested Up To
WordPress 7.0
Requires PHP
8.0

Share Post

Join our newsletter.

Get insights into what’s happening at ChangelogWP right in your inbox. We don’t believe in spam.