Moving a WordPress site: 8 things that break, and how we fixed them

6 min readWordPressmigrationbackups

A 35 GB archive “without media”, a site that crashes for no reason, passwords that stop working and broken links in ACF. What causes each one, how to fix it by hand, and why we ended up writing our own plugin.

We move WordPress sites all the time: local to staging, staging to live, one host to another. And every time we step on the same rakes. The last project collected nearly all of them in two days, so we wrote each one down: what happened, why, how to fix it by hand, and what we did about it in the plugin we ended up writing for ourselves.

1. “Without media” - and the archive is 35 GB

You tick “exclude media” and the migration plugin still builds 35 GB. The reason is that wp-content holds more than the site. There are copies like uploads-old and plugins-old that someone made “just in case”, and backups from other plugins: UpdraftPlus, All-in-One, Duplicator. The checkbox only drops the uploads folder; everything else goes into the archive.

# what actually takes the space in wp-content
du -sh wp-content/* | sort -rh | head -15
Before exporting, look at what takes the space.

In our plugin, other plugins' backups, caches and *-old, *-backup, *.bak copies at the top of wp-content are always skipped. The export screen also shows the biggest folders, and any of them can be left out with one click.

2. The site crashes after the move, although it worked on the old server

We restored a production backup locally and got a critical error instead of the site. The log said: Failed opening required '/scripts/object-cache.memcache.php'. The culprit was wp-content/object-cache.php. It is a host “drop-in”: it plugs in the host's cache and only exists on their servers. It travelled with the backup to a machine without that cache and took the site down.

# on the new server: switch off the old host's drop-ins
mv wp-content/object-cache.php   wp-content/object-cache.php-off
mv wp-content/advanced-cache.php wp-content/advanced-cache.php-off

It works the other way round too: overwrite a host's own object-cache.php during an import and the site will not crash, but it loses its caching. So our plugin neither moves object-cache.php, advanced-cache.php and db.php nor overwrites them on the server it imports into.

3. After the import the password does not work

This is not a bug but a consequence: the users move together with the database. After the import you log in with the username and password of the old site, not the one you imported into. The confusion starts when the two sites have different admins and nobody thought to warn you.

# forgot the old site's password - set a new one
wp user update admin --user_pass="new-strong-password"

Our plugin says this right on the screen after the import and offers a “Log in again” button. A small thing, but it takes away half the panic.

4. Links to the old domain in widgets, page builders and ACF

The sneakiest one. WordPress stores many settings serialized: a string remembers its own length. Replace the domain with a plain find-and-replace in an SQL dump and the length changes while the record does not. PHP can no longer read it, and the widget, ACF block or theme setting quietly disappears.

# WP-CLI knows about serialized data; plain sed on a dump does not
wp search-replace 'https://old-site.com' 'https://new-site.com' --all-tables --precise

Our plugin rewrites addresses and paths by itself, parsing serialized values and recomputing their lengths, and it also catches JSON-escaped links (https:\/\/...). After the import, the Tools tab shows where the old address is still stored and replaces it everywhere in one click.

5. The site has moved but still shows the old version

The import finished, the database is new, and visitors still see old pages. That is the page cache (WP Rocket, LiteSpeed, W3 Total Cache) serving stored copies, plus the object cache holding old settings in memory. We stared at the “wrong” page for a minute ourselves before noticing the WP Rocket marker in the source.

wp cache flush   # object cache
# page cache: "Clear cache" in WP Rocket / LiteSpeed / W3 Total Cache

Our plugin clears the WP Rocket, W3 Total Cache, LiteSpeed, WP Super Cache, Autoptimize and SiteGround caches after an import, plus the object cache.

6. Only the database was moved - and images disappeared

To avoid hauling gigabytes, people move only the database and the theme. But if new images were added on the old site in the meantime, the database now points at them while the files are missing on the new server. That is how two icons vanished from our home page: the media library entries were there, the files were not.

# copy only the months that changed, not the whole uploads folder
rsync -av old-server:wp-content/uploads/2026/10/ wp-content/uploads/2026/10/

For cases like this our plugin has changes-only backups: they pack only the files changed since a full backup. They are quick to move, and restoring one lays the changes over the full backup by itself.

7. The safety backup takes more space than the import itself

The right habit is to back up before an import. But we were importing a 165 MB archive (database and theme), and the “backup first” step started packing the whole site with 22 GB of media. On a host with limited disk space, that ends with no room left for the import itself.

Now the safety backup in our plugin covers only what the import will overwrite: if the archive holds the database and themes, the database and themes are backed up. A minute instead of an hour.

8. The import stopped halfway

The host kills the request after 30-60 seconds, the browser loses the connection, and the import stops halfway. The worst case is when half the tables are already new and half are still old.

In our plugin everything runs in short steps that resume where they stopped. The new database is loaded into temporary tables first, and the live site switches to it in a single operation at the very end. If something breaks before that, the site never notices. And the previous database is kept for 7 days: if something is off after the import, “Undo import” puts everything back.

Why we wrote our own plugin

Each of these problems can be worked around by hand, and the commands above are exactly that. But when you move sites every week, you want the tool itself to know about drop-ins, serialized data, caches and other plugins' backups. So we put all of it into WinOnWeb Migrate. It is completely free: no size limit, no paid extensions, and it can import All-in-One and Duplicator archives, so switching does not mean repacking anything.

  • No size limit: export, upload and import in chunks.
  • Imports All-in-One (.wpress) and Duplicator (.zip) archives.
  • Safe import through temporary tables, with undo for 7 days.
  • Smart address replacement, including serialized data and ACF.
  • A finder for leftover old links after the move.
  • Scheduled backups with a changes-only mode.

You can download the plugin and read how to use it at winonweb.dev/en/migrate.