Relocating a WordPress website between servers, changing a domain name, or moving from an insecure protocol to HTTPS requires updating domain references throughout the database. Simply running a standard database query to replace text strings often causes severe configuration breakage. Understanding how WordPress stores complex data structures enables administrators to transition web addresses cleanly while keeping layouts, widgets, and theme configurations fully intact.
The Underlying Risk: PHP Data Serialization
When WordPress stores simple information like a post title, it uses plain text in the database. However, modern themes, page builders, and complex plugins regularly bundle structured arrays and objects into single database cells. WordPress saves these multidimensional records using PHP serialization. A serialized string records not only the data values but also their explicit byte lengths. For example, an entry containing a website address might record the string length alongside the text, formatted similarly to s:18:"https://old-site.ca";.
If you execute a standard SQL statement such as UPDATE wp_options SET option_value = REPLACE(...), the database modifies the text without recalculating the character length descriptor. If the stored byte count no longer matches the value, PHP cannot reliably decode the serialized string. It may return false and report a warning; the failed read does not itself erase the stored database row. As noted in the official WordPress migration documentation, replacing URLs across an entire database without accounting for serialization corrupts widgets, theme settings, and custom field values. Preserving these configurations requires tools designed to parse serialized strings, update values, and recalculate byte counts before writing to disk.
Preparing for the Migration Routine
Database adjustments should never occur without multiple recovery layers in place. Before initiating any string replacements, take methodical preparatory steps:
- Create a complete database dump: Export the database through your web hosting control panel, phpMyAdmin, or command-line database tools. Verify that the backup file is fully written and accessible.
- Audit administrator credentials: Ensure that database access is strictly isolated to authorized personnel. Reviewing elevated administrative permissions through proper WordPress roles and capabilities management prevents unauthorized modifications during sensitive maintenance windows.
- Confirm table prefixes: Check
wp-config.phpto confirm whether your installation uses the defaultwp_prefix or a custom prefix, which affects search scopes in specialized scripts. - Put the site in maintenance mode: Plan a write freeze or controlled cutover, including orders, forms, background jobs and integrations. A visitor-facing maintenance page alone does not stop cron or external writes.
Method 1: Utilizing WP-CLI Search and Replace (Recommended)
For administrators with shell access, the official command-line interface provides the most robust mechanism for modifying records. The WP-CLI search-replace tool safely handles PHP serialized data without modifying primary key values. The utility processes every column while recalculating string lengths accurately.
Step 1: Execute a Dry Run
WP-CLI includes a simulated testing mode. This command queries the database, identifies matches, and displays a summary table of changes without modifying any data:
wp search-replace 'https://old-domain.ca' 'https://new-domain.ca' --skip-columns=guid --dry-run
Review the output to see how many replacements are slated across tables like wp_options, wp_posts, and wp_postmeta. If the numbers appear unexpectedly high or low, double-check your syntax and protocol prefixes.
Step 2: Account for GUIDs and Custom Tables
By default, WordPress standards recommend preserving the Globally Unique Identifier (GUID) column in the wp_posts table. RSS readers use the GUID to track read versus unread posts; changing it can cause feed readers to treat existing posts as new items. Additionally, third-party plugins occasionally generate custom database tables that are not registered in the global database handler.
Review which custom tables actually need replacement; logs and archives may need to retain historical URLs. If all tables with this site’s prefix are intentionally in scope, use the following flags in both the dry run and the live command, removing only --dry-run after review:
wp search-replace 'https://old-domain.ca' 'https://new-domain.ca' --skip-columns=guid --all-tables-with-prefix
Step 3: Flush Object and Transient Caches
Database updates bypass WordPress runtime caches. After completing the search and replace, flush the object cache so the application serves new values immediately:
wp cache flush
Method 2: Evaluating Dashboard Plugin Candidates
If command-line access is unavailable through your hosting environment, specialized plugins can perform safe database replacements inside the administration panel. Evaluate a tool that explicitly supports serialized data, preview mode and the intended tables, such as Better Search Replace; confirm its current documentation before use.
When using a plugin-based utility, follow these operational precautions:
- Run dry runs first: Verify whether the candidate tool includes a preview or test mode before applying permanent updates.
- Process in smaller batches: Shared hosting environments often enforce strict PHP execution limits. Selecting every database table at once can cause a script timeout midway through a table write. Process core tables such as
wp_postsandwp_postmetaseparately from analytical or log tables. - Remove the tool after completion: Database replacement plugins contain powerful capabilities. Deactivate and delete them once your migration verification is finished to reduce your attack surface.
Hypothetical Migration Example
Consider a hypothetical Canadian company, Maple Supply Goods, moving its online catalogue from a staging environment (https://staging.maplesupply.ca) to its primary production domain (https://maplesupply.ca). During staging, the team populated dozens of product pages and customized navigational menus, which also incorporate carefully structured WordPress category and subcategory hierarchies.
The administrator logs in over SSH and executes a preliminary dry run:
wp search-replace 'https://staging.maplesupply.ca' 'https://maplesupply.ca' --skip-columns=guid --dry-run
The dry-run report indicates that wp_options contains 42 instances, wp_posts contains 310 instances, and wp_postmeta contains 188 instances. Because these instances include serialized layout parameters, running standard SQL queries would have corrupted the homepage layout. The administrator runs the live command with GUID protection:
wp search-replace 'https://staging.maplesupply.ca' 'https://maplesupply.ca' --skip-columns=guid
The command executes successfully in four seconds, updating serialized byte counts in the metadata. The administrator clears the server cache and inspects both product listings and category archive layouts, finding every element rendered accurately.
Troubleshooting Common Post-Migration Failures
| Symptom | Probable Cause | Resolution Action |
|---|---|---|
| Empty theme options or missing widget areas | Direct SQL updates broke serialized length counts in wp_options |
Restore the backup database and re-run replacements using a serialization-safe tool |
| Mixed content warnings in browser console | Hardcoded HTTP resources or background images stored in static CSS | Check custom CSS files or search specifically for the HTTP protocol string |
| Site redirects back to the previous address | home and siteurl options still contain old values |
Update core options via WP-CLI (wp option update home ...) or wp-config.php constants |
| Database script timeouts or HTTP 504 errors | Table sizes exceed PHP execution memory or execution time ceilings | Switch to WP-CLI via terminal or select tables in individual smaller batches |
Canada Create™ builds and optimizes WordPress sites for Toronto businesses. Tell us your goals and we will recommend the right setup.
Migration URL Replacement Checklist
- Create and verify a complete, restorable database backup prior to any search operation.
- Identify all domain variations requiring replacement, including protocol variations (HTTP vs HTTPS) and subdomain prefixes (www vs non-www).
- Execute a dry run to inspect matched row counts across options, metadata, and post content.
- Preserve the
guidcolumn to avoid triggering feed reader duplicate notifications. - Clear persistent server object caches, persistent transients, and external reverse-proxy caches immediately following replacement.
- Test front-end template components, custom navigation menus, and media library attachments to confirm structural integrity.
Frequently Asked Questions
How do I update URLs after a WordPress migration?
Use a serialization-safe search and replace tool, such as WP-CLI, to change the old domain to the new one.
Why not use plain SQL find and replace?
It breaks serialized data in options and widgets.
Do I need redirects after changing domains?
Yes. 301 redirects preserve traffic and rankings.
Who can migrate my WordPress site?
Our web hosting team.


