Moving your WordPress site to a new host sounds simple — copy the files, move the database, point the domain. In practice, it is one of the easiest ways to silently break a site: layouts vanish, images 404, contact forms stop sending, and nothing tells you why. This guide shows you how to migrate a WordPress site the right way, step by step, with two methods — the fast plugin route and the full manual route — plus the serialization trap that ruins most DIY moves and the post-move checklist that catches silent failures.
Before you touch anything: the pre-migration checklist
Do these on the old host, before a single file moves:
- Take a complete backup — files and database, stored somewhere other than the server you’re leaving. A migration is not a backup.
- Update everything first. WordPress core, plugins, and the theme. Migrating outdated software just moves the vulnerability to the new server.
- Note your current setup: PHP version, the plugins you actually use, custom code snippets in the theme or a plugin like Code Snippets, and any cron jobs (WP-Cron schedules you added, or server-side cron tasks).
- Lower your DNS TTL to 300 seconds (5 minutes) 24–48 hours before the move. DNS records cache across the internet; a long TTL means visitors keep hitting the old server for hours after you switch. Lowering it early makes the cutover fast.
- Check the new host’s requirements. Minimum: PHP 8.1+ (8.2 or 8.3 is what you want in 2026), MySQL 8.0 or MariaDB 10.6+, enough disk space, and SSH access if you plan to use WP-CLI.
Method 1: The plugin route (fastest for most sites)
If your WordPress site is a standard brochure site or blog and both hosts are cooperative, a migration plugin is the honest fastest path. Duplicator (free version is enough for most sites) or All-in-One WP Migration both package the site into a single archive + installer file.
The workflow:
- Install the plugin on the old site and build the package.
- Upload the archive and installer to the new host’s web root.
- Open your-domain.com/installer.php and follow the wizard — it creates the database tables and rewrites URLs for you.
- Delete the installer files when done. Leaving installer.php on a live server is a genuine security risk; every reputable migration plugin warns you about this, and you should treat it as mandatory.
Limits to know: free plugin tiers often cap archive size (All-in-One WP Migration’s free import limit is famously small — large media libraries will need the paid extension). On cheap shared hosting, the packaging step itself can time out on big sites. If you hit limits, the manual method below always works.
Method 2: Migrate a WordPress site manually (full control)
This is the method I use for client sites, because nothing hides. It also teaches you how WordPress actually fits together: files, database, config.
Step 1: Export the database
From phpMyAdmin on the old host: select the database, Export → Quick, format SQL, download. Or over SSH:
mysqldump -u olduser -p olddbname > site-backup.sql
Step 2: Download the WordPress site files
Use SFTP/FTP and pull down everything — at minimum wp-content/, plus .htaccess if you run Apache. You can skip wp-content/cache/ and any backup folders your backup plugin created inside the site (they just bloat the transfer).
Step 3: Create the new database and user
On the new host, create an empty database and a database user with full privileges on it. Note the database name, username, password, and host (often localhost, sometimes a separate DB hostname on managed hosts).
Step 4: Upload the files and update wp-config.php
Upload everything to the new web root. Then edit wp-config.php — the four lines that connect WordPress to the database:
define( 'DB_NAME', 'new_db_name' );
define( 'DB_USER', 'new_db_user' );
define( 'DB_PASSWORD', 'your_strong_password' );
define( 'DB_HOST', 'localhost' );
Double-check for typos; a single wrong character here gives you the classic “Error establishing a database connection” screen.
Step 5: Import the database
Create the empty database first (step 3), then import:
mysql -u newuser -p newdbname < site-backup.sql
Or use phpMyAdmin’s Import tab on the new host.
Step 6: Run a serialization-safe search-replace
This is the step where most manual migrations fail. If your domain changes — even from http://staging.example.com to https://example.com — you must update the old URLs stored in the database. But you cannot just open the SQL file and find-and-replace the domain.
WordPress stores widgets, theme options, and plugin settings (including Elementor layouts) as serialized PHP: every string is stored with its length, like s:22:”http://old-domain.com/”. A naive find-and-replace in a text editor changes the string but not the recorded length, so WordPress can’t unserialize the value and silently drops it. Your content imports fine, but your menus, widgets, and page-builder layouts disappear with no error message.
The safe way is a tool that understands serialization. With SSH and WP-CLI (my recommendation), run a dry run first, then the real thing:
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --all-tables --skip-columns=guid --dry-run
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --all-tables --skip-columns=guid
Two notes on those flags: –skip-columns=guid leaves the guid column alone, because GUIDs are meant to be permanent identifiers, not URLs (changing them can confuse feed readers). –all-tables covers plugin tables too — many plugins store full URLs in their own tables.
No SSH? Use the Better Search Replace plugin (it handles serialized data correctly) or the standalone Search-Replace-DB script — upload it to a hard-to-guess folder, run it, and delete it immediately after. Left on the server it gives anyone who finds it full write access to your database.
If you’re moving the same domain between servers, run the same search-replace for old server paths (e.g. /home2/olduser/public_html → the new document root) — caches, logs, and upload-path settings sometimes store those.
Step 7: Point DNS and finish up
Update your A record to the new server’s IP (remember you lowered the TTL, so this propagates fast). Then:
- Visit Settings → Permalinks and click Save Changes without changing anything. This regenerates .htaccess rewrite rules on the new server.
- Check Settings → General — WordPress Address and Site Address should show the new domain.
- Clear any server or plugin caches on the new host.
The post-migration verification checklist
A WordPress site migration isn’t done when the homepage loads. Run through these before you consider it finished:
- Homepage, a post, a page, and the contact page all load over HTTPS with no mixed-content warnings.
- Images and media library items display (404 images are the classic sign of a bad URL swap).
- Menus, widgets, and page-builder layouts are intact (the serialization check).
- Submit the contact form and confirm the email arrives — migrations quietly break outbound mail, and password resets disappearing is how you discover it at the worst moment.
- https://your-domain.com/wp-json/wp/v2/posts returns valid JSON (catches rewrite/mod_rewrite issues on the new server).
- WooCommerce sites: place a test order and confirm payment webhooks fire.
- Log into wp-admin, check for update nags, and re-run a speed test — a slow new host shows up immediately. (See my guide on reducing server response time if TTFB looks worse than before: https://amaar.site/reduce-server-response-time-wordpress/)
- Restore your DNS TTL to its normal value (e.g. 14400).
Common migration failures and quick fixes
White screen or “Error establishing a database connection.” Wrong credentials in wp-config.php, or the DB user lacks privileges on the new database. Re-check all four defines and the user’s grants.
Homepage works, everything else 404s. Permalinks weren’t flushed, or the new server lacks rewrite support. Save permalinks again; on Apache confirm mod_rewrite is enabled and .htaccess is writable; on nginx, make sure the host’s WordPress rewrite rules are in place.
Mixed content warnings (HTTPS page loading HTTP assets). The search-replace missed some URLs — often http:// variants. Run it again for the http:// version of the old domain, and check wp_options for stragglers.
Emails stopped working. The old host may have handled mail locally. If your MX records pointed at the old host, mail broke the moment DNS moved. Decide deliberately: keep mail with Google Workspace/365 or a transactional provider, and make sure SPF/DKIM records still match your sending setup.
Site is slower than before. New host, new performance profile. Run PageSpeed Insights and compare against your pre-migration numbers. My INP optimization guide (https://amaar.site/improve-inp-wordpress/) and server response time guide (https://amaar.site/reduce-server-response-time-wordpress/) cover the usual suspects.
Which method should you choose?
For a standard WordPress site under ~1 GB with no exotic server config, Duplicator’s free tier gets you moved in under an hour. For client sites, WooCommerce stores, or anything where you need to know exactly what happened at every step, do it manually — the 30 extra minutes buy you certainty, and the WP-CLI search-replace is the single most reliable URL swap in the WordPress ecosystem.
One last rule I follow on every WordPress site migration: keep the old site (and its backup) untouched for a week. If something subtle surfaces days later — a scheduled post that never fired, a webhook nobody tested — you still have the original to compare against.
Further reading on manual migrations: https://dev.to/bozhidar_valchev/manual-wordpress-migration-step-by-step-pnl (opens in new tab) and https://www.hostmycode.com/tutorials/wordpress-migration-tutorial-2026-move-shared-hosting-to-vps-without-downtime-ssl-email (opens in new tab).
Moving to a new host, or worried your current one is holding your site back? I handle WordPress migrations, speed optimization, and hardening for clients — get in touch: https://amaar.site/contact/