How to Move a WordPress Site From Staging to Live
The copying is routine; the URL rewrite is what breaks sites. Here is why find-and-replace corrupts page-builder layouts, the two URL forms most tools miss, and the safe order to migrate in.
By WP MegaManager Team
Moving a WordPress site from staging to live means copying two things — the database and the files — and then rewriting every reference to the old domain so the new one works. The copying is routine. The rewrite is where migrations break, and the reason is not obvious: WordPress stores some of its most important settings in a format that records the length of every value, so a plain find-and-replace corrupts them silently.
This guide covers what actually breaks, why, and the safe order to do it in.
What a staging-to-live migration involves
| Part | What moves | Risk |
|---|---|---|
| Database | Posts, pages, options, widget config, builder layouts | High — this is where URLs hide |
| Files | Themes, plugins, uploads | Low — a straight copy |
| Domain rewrite | Every stored occurrence of the staging URL | Highest |
| Live site's own data | Orders, form entries, new users since the fork | Destroyed unless preserved |
That last row is the one people discover too late. A staging build is a snapshot of the site as it was when the fork happened. Everything the live site collected since then — orders, form submissions, comments, new registrations — is not in that snapshot. Pushing staging over live deletes it. A shop is rarely a safe candidate for a full push.
Why find-and-replace corrupts WordPress sites
WordPress stores widget settings, theme mods, and page-builder layouts as PHP-serialized data. Serialization writes the byte length of every string alongside it:
s:29:"https://staging.example.com/"
The 29 is a promise: the next value is exactly 29 bytes. Replace staging.example.com with example.com using a text editor or a SQL REPLACE() and you get:
s:29:"https://example.com/"
The string is now 21 bytes, but the record still claims 29. PHP's unserialize() refuses the whole structure and returns false. WordPress receives nothing where it expected an array of settings, and falls back to defaults.
This is why Divi and Elementor modules come back blank after a manual migration. The layout was not deleted; it became unreadable. The same failure hits widget areas, theme customizer settings, and any plugin storing arrays in wp_options.
A correct rewrite decodes the structure, replaces inside it, and re-encodes — so the lengths are recalculated rather than invalidated.
Two forms people miss
Even a serialization-aware replace fails if it only looks for the plain URL. Two other encodings appear in real databases:
- JSON-escaped — page builders storing layouts as JSON write
https:\/\/staging.example.com. The forward slashes are escaped, so a search forhttps://never matches. - Protocol-relative —
//staging.example.com/image.jpg, common in theme options and hard-coded asset paths.
Both need handling in the same pass.
Methods compared
| Method | Serialization-safe | Effort | Good for |
|---|---|---|---|
| Export/import via phpMyAdmin + text editor | No | High | Nothing — this is the one that breaks builders |
SQL REPLACE() query | No | Low | Plain text only, never options |
WP-CLI search-replace | Yes | Medium | Developers with SSH access |
| Migration plugin (Duplicator, All-in-One WP Migration) | Usually | Medium | One-off single-site moves |
| Management platform with transfer | Yes | Low | Agencies moving sites regularly |
If you have shell access, wp search-replace 'staging.example.com' 'example.com' --all-tables is the reliable free answer — WP-CLI handles serialized data correctly. Add --dry-run first to see the count before committing.
The safe order
- Back up the live site first, not the staging one. The destination is the thing you can lose. A migration that fails before this step has changed nothing; one that fails after it is recoverable. Everything else in this list is reversible only because of this backup.
- Check what live has collected. Orders since the fork, form entries, new users. If any exist, decide explicitly whether they are being discarded or need to be merged back afterwards.
- Copy the database and files from staging.
- Rewrite URLs with a serialization-aware tool, covering the plain, JSON-escaped and protocol-relative forms.
- Preserve anything the live site must keep — licence keys, analytics IDs, SMTP credentials, and any plugin paired to the live domain. These live in
wp_optionsand will be overwritten by the staging copy unless you snapshot and restore them. - Flush caches and permalinks. Visit Settings → Permalinks and save once; object and page caches should be cleared at the same time.
- Verify before announcing. See the checklist below.
Post-migration checklist
- Home page, a blog post, and one page built with your page builder — all rendering correctly
- Widget areas and menus populated, not empty
- Media library images loading (broken thumbnails mean the uploads path or URL rewrite missed something)
- Contact form submitting and delivering
- Checkout completing, if it is a shop
site_urlandhomein Settings → General pointing at the live domain- No staging URLs left: search the database for the old domain and expect zero rows
- Search Console: the live domain still indexed, no sudden
noindex(staging sites usually carryDiscourage search engines— this setting migrates with the database and will de-index a live site overnight)
That last one deserves its own warning. The single most common post-migration disaster is not a broken layout — it is the staging site's "discourage search engines" flag arriving with the database. Check Settings → Reading immediately.
Frequently asked questions
Can I just copy the wp-content folder? No. Content, settings, menus and layouts live in the database, not in files. Files alone move themes and uploads and nothing else.
Does the live site keep its SSL certificate? Yes — certificates are attached to the domain and server, not to the WordPress database, so they are unaffected by a migration.
What if the two sites use different table prefixes? Most migration tools do not translate prefixes. Match them before migrating, or you will get a database WordPress cannot read.
How do I undo a migration that went wrong? Restore the backup of the live site taken in step 1. This is the only reliable undo, and it is why that step is first.
Doing this regularly
If you rebuild client sites on staging as a matter of course, the manual version of this gets expensive — and every manual run is another chance to skip the backup.
WP MegaManager's site transfer runs the whole sequence in a fixed order: it backs up the destination first, copies the source, then rewrites the URLs with a serialization-aware pass that handles the escaped and protocol-relative forms too. The destination keeps its own connection to the platform rather than inheriting the source's identity, and undo is a normal restore from the destination's backups. The full procedure is documented in Transferring a site.
Manage all your WordPress sites from one dashboard
Bulk updates, cloud backups, uptime monitoring, security and AI automation — in one place.
Start Free Beta