Moving a WordPress site between domains, servers, or hosting providers has always been one of the most dreaded tasks in WordPress management. Between serialized data in the database, hardcoded URLs in theme settings, and the logistics of transferring gigabytes of files, migration is where most backup plugins fall short. Emnes Backup Migrate Reset was built from the ground up to handle both restoration and cross-domain migration seamlessly. Here is how it works.
The Migration Workflow: Step by Step
Migrating a WordPress site with Emnes Backup Migrate Reset is a straightforward three-step process:
- Export — On the source site, create a full backup and click Export. The plugin bundles the entire backup directory into a single downloadable ZIP file.
- Import — On the destination site, install Emnes Backup Migrate Reset and use the Import feature to upload the exported ZIP file.
- Restore — Choose which components to restore. The plugin automatically detects that the backup came from a different domain and performs URL search-and-replace during database restoration.
No manual database editing, no search-replace plugins, no phpMyAdmin — everything is handled in the plugin’s admin interface.
Smart Export Packaging
When you click Export on a backup, the plugin bundles the entire backup directory — all split ZIP archives, the database dump, the manifest, and the checksums file — into a single downloadable ZIP named ebmr-export-{nonce}.zip. The file is streamed directly to your browser with proper Content-Disposition headers, so you get a clean download without the file consuming permanent server storage.
The export ZIP is automatically cleaned up: a shutdown function deletes the temporary file after the download completes. Even if something goes wrong, stale export ZIPs older than one hour are cleaned up automatically on every page load.
Secure Import with ZIP Bomb Protection
Importing a backup on the destination site is not just a matter of extracting a ZIP file. Malicious or malformed archives can be used to attack servers — a technique known as a ZIP bomb, where a small compressed file expands to terabytes of data. Emnes Backup Migrate Reset validates every imported archive with multiple layers of protection:
- Maximum 500 entries — Archives with more than 500 files are rejected.
- 2 GB total uncompressed limit — The total uncompressed size of all entries must not exceed 2 GB.
- 512 MB per-file limit — No single file in the archive may exceed 512 MB uncompressed.
- Maximum path depth of 20 — Deeply nested directory structures are rejected.
- Path traversal prevention — Entries containing
.., absolute paths, or backslashes are rejected. - Extension validation — Only
.zipfiles are accepted as imports. - Content validation — The archive must contain at least one recognized backup file (
.sql.gz,.sql, or{component}-part{N}.zip) to be accepted. - Disk space check — Free disk space is verified before extraction begins.
All size limits are configurable via filters for sites that legitimately need to import larger backups.
The Restore Process in Detail
Whether you are restoring a backup on the same site or migrating to a new domain, the restore process follows a carefully orchestrated sequence designed to minimize downtime and prevent data corruption.
1. Pre-Restore Validation
Before touching any data, the restore manager performs several safety checks:
- Semaphore lock — Acquires an atomic MySQL lock to prevent concurrent restore operations.
- Manifest check — Reads the backup’s
manifest.jsonto understand what components are available. - Version compatibility — Verifies the backup was made with a compatible plugin version.
- Checksum verification — If
checksums.jsonis present, SHA-256 hashes of every backup file are verified before starting. If any file is corrupt, the restore is aborted before any changes are made.
2. Maintenance Mode
The plugin writes a .maintenance file to put WordPress into maintenance mode. This prevents visitors from seeing a broken site while the restore is in progress. The file location is Bedrock-aware — it is placed at dirname(WP_CONTENT_DIR)/.maintenance for Bedrock installations, or ABSPATH/.maintenance for standard WordPress. The maintenance file is always removed in a finally block, ensuring it is cleaned up even if the restore fails.
3. User Session Capture
A database restore replaces the entire wp_users and wp_usermeta tables, which invalidates the current admin’s session. Before starting, the restore manager captures the current user’s ID. After the database is restored, it calls get_userdata() on that ID and re-authenticates the user with wp_set_auth_cookie() and wp_set_current_user(). This means the admin stays logged in throughout the restore process — no unexpected logouts.
4. Database Restoration
The database restore driver reads the SQL dump line by line — supporting both gzipped (.sql.gz) and uncompressed (.sql) formats. It handles:
- Multi-line SQL statements (accumulates lines until a semicolon terminator is found)
- MySQL conditional comments (
/*!...*/) executed immediately - Comment lines (
--) and empty lines are skipped - Every 25 statements, the PHP timeout is refreshed and the semaphore lock is renewed
5. Preserved Options
When restoring a database from another site (or even the same site at a different point in time), certain options must be preserved to maintain the current site’s identity. Before the restore begins, the plugin captures:
siteurl— The WordPress addresshome— The site addressblogname— The site titleblogdescription— The site taglineadmin_email— The admin email address
After the database restore completes, these values are written back to the restored database. You can customize this list with the ebmr_preserved_options filter — for example, adding WooCommerce payment gateway API keys that should never be overwritten by a backup.
URL Search-and-Replace: The Heart of Migration
This is where most backup plugins either fail or require a separate tool. When you restore a backup from https://staging.example.com onto https://www.example.com, every URL in the database needs to be updated — in post content, widget settings, theme customizer values, plugin configurations, and serialized options.
Automatic Detection
The plugin detects migration automatically. During the restore modal, if the backup’s source site URL differs from the current site URL, a migration notice is displayed. The user can also provide the source URL manually. The plugin then triggers the search-and-replace engine automatically — no separate step required.
Three Search-Replace Pairs
For each migration, the plugin generates three search-replace pairs to cover all URL encoding formats found in WordPress databases:
- Exact URL —
https://old-domain.comtohttps://new-domain.com - Trailing-slash-trimmed — Handles URLs stored with or without trailing slashes
- JSON-escaped —
https:\/\/old-domain.comtohttps:\/\/new-domain.com(for URLs stored in JSON-encoded strings within the database)
Serialization-Safe Replacement
This is the most critical part. WordPress stores many options and widget configurations as PHP serialized strings. A serialized string looks like this:
s:45:"https://old-domain.com/wp-content/uploads/logo.png";
The s:45 prefix means “string of 45 bytes.” If you do a naive find-and-replace changing the domain, the string length changes but the byte count prefix does not — and PHP’s unserialize() will fail, corrupting your data silently.
Emnes Backup Migrate Reset handles this correctly for every table with a primary key:
- Rows are fetched in batches (default 500, configurable via
ebmr_search_replace_batch_size), filtered with aWHERE LIKE '%search%'clause to only process rows that actually contain the old URL. - Each column value is checked: if it is a serialized string, it is unserialized into a PHP object/array.
- The replacement is performed recursively through the entire data structure — arrays, nested arrays, objects, and string values at any depth.
- The data is re-serialized, producing correct byte count prefixes automatically.
- The row is updated with the corrected value.
Handling Incomplete Classes
When WordPress encounters a serialized object whose class is not loaded (because the plugin that defined it is not active during the restore), PHP creates a __PHP_Incomplete_Class object. The plugin handles this gracefully: it serializes the incomplete object back to a string and uses a custom fixSerializedStringLengths() method to correct the s:N byte count prefixes after replacement. This ensures that even serialized objects from plugins you do not have installed will survive the migration intact.
Tables Without Primary Keys
For tables that lack a primary key (which makes row-by-row updates impractical), the plugin falls back to SQL-level replacement:
UPDATE table_name SET column = REPLACE(column, 'old-url', 'new-url')
This works for non-serialized data. Tables without primary keys typically contain non-serialized data (logs, analytics, etc.), so this trade-off is acceptable.
File Restoration
File restoration is equally thoughtful. The file restore driver opens each ZIP part archive and performs a clean restore:
- Directory cleanup — Files in the target directory that are not present in the backup are removed, giving you a clean state. The plugin never deletes its own backup directory (
emnes-backup-migrate-reset/) during this process. - Self-protection — ZIP entries that start with
emnes-backup-migrate-reset/are skipped during extraction, preventing the plugin from overwriting itself mid-restore. - Cache clearing — After file restoration, the plugin clears all relevant WordPress caches:
wp_cache_flush(),wp_clean_plugins_cache(),wp_clean_themes_cache(). It also integrates with popular caching plugins — WP Super Cache, W3 Total Cache, LiteSpeed Cache, and WP Fastest Cache — calling their respective cache-clearing functions. Third-party cache plugins can hook into theebmr_clear_cacheaction.
Selective Component Restore
You do not have to restore everything. The restore modal lets you choose exactly which components to restore from the backup:
- Restore only the database (to undo a bad data change)
- Restore only plugins (to revert a plugin update)
- Restore only themes (to revert a theme change)
- Restore the database and uploads (to recover lost media and the posts that reference them)
- Restore everything for a complete site recovery
Each component shows its size in the modal, so you know what you are working with before committing.
Cross-Site Migration Indicators
The backup list in the Restore page shows the origin of each backup with a clear badge:
- “This site” — The backup was created on the current site.
- Hostname badge — If the backup came from a different site (via import), the source domain is displayed.
- “Unknown” — If the source site URL is not available (e.g., very old backups without metadata).
This makes it immediately clear which backups will trigger a migration workflow and which are same-site restores.
Database Reset: Starting Fresh
Sometimes you do not want to restore — you want a clean slate. The Database Reset feature drops all WordPress tables, runs wp_install() to create a fresh database, and then optionally:
- Reactivates your theme — Switches back to your previously active theme.
- Reactivates your plugins — Activates all previously active plugins.
- Keeps the plugin active — Ensures Emnes Backup Migrate Reset itself stays active after the reset.
- Clears uploads — Optionally deletes all uploaded files.
- Clears media only — Deletes only the
YYYY/MM/media library directories, leaving other uploads intact.
The reset preserves your admin credentials (username, email, and password hash) and restores the site URL and blog name. Plugin settings are also re-imported automatically. A safety confirmation requires typing “RESET” to prevent accidental triggers.
Summary
Emnes Backup Migrate Reset turns WordPress migration from a multi-tool, multi-step ordeal into a simple export-import-restore workflow. Serialization-safe URL replacement, ZIP bomb protection, automatic maintenance mode, session preservation, and selective component restore make it a reliable choice for agencies and developers who manage dozens of WordPress sites across different environments.