How to Migrate WordPress to a New Host Without Any Downtime
Reduce TTL, export, import, test on staging, switch DNS. Zero downtime migration in under 2 hours.
In This Guide
How to Migrate WordPress to a New Host Without Downtime
Migrating WordPress is one of those tasks that sounds simple and has a hundred ways to go wrong. Database character encoding issues, hard-coded URLs in post content, file permission problems, SSL certificate timing — any of these can cause your site to appear broken on the new host while the old one is still live, or leave visitors hitting errors during the switchover.
This guide covers the migration process correctly, including the steps most tutorials skip.
Before You Migrate: The Preparation Checklist
Document Your Current Setup
Before touching anything:
# Record your current PHP version
php -v
# Record your WordPress version (check wp-admin → Dashboard → Updates)
# List active plugins (Tools → Site Health → Info → Active Plugins)
# Note your domain configuration
# - Does your site use www or non-www?
# - Are there any subdomains?
# - Do you have any domain redirects configured?
Save this information. When something breaks on the new host, you'll need it.
Create a Fresh Baseline Backup
Don't rely on your existing automated backups for a migration. Create a fresh backup immediately before starting:
Database backup:
# Via WP-CLI (most reliable)
wp db export backup-$(date +%Y%m%d).sql --add-drop-table
# Via phpMyAdmin: select all tables, Export → Quick, SQL format
# Via mysqldump (SSH access required)
mysqldump -u DB_USER -p DB_NAME > backup-$(date +%Y%m%d).sql
Files backup:
# Compress everything except the database
tar -czf wp-files-$(date +%Y%m%d).tar.gz \
--exclude='./wp-content/cache' \
--exclude='./wp-content/backups' \
.
The cache exclusion matters — cache directories can contain gigabytes of files that don't need to be migrated and will slow down the transfer significantly.
Setting Up the New Host
Provision your new hosting environment before touching the migration. On a container-based platform:
- Create a new WordPress installation
- Note the internal database hostname, database name, username, and password
- Confirm the domain is not yet pointing to the new host (you'll use a staging URL to test)
- Verify SSL is provisioned on the staging URL
Do not set up the final domain on the new host yet. You want the ability to test the migration before the DNS switch.
The Migration Process
Step 1: Export the Database
# WP-CLI (on old host)
wp db export migration.sql --add-drop-table
The --add-drop-table flag adds DROP TABLE IF EXISTS statements before each CREATE TABLE, which ensures a clean import even if there are leftover tables from a fresh WordPress installation.
Step 2: Transfer Files
For most migrations, you only need wp-content:
# On old host — create archive of wp-content
tar -czf wp-content.tar.gz \
--exclude='./wp-content/cache' \
--exclude='./wp-content/upgrade' \
wp-content/
# Transfer to new host (via SCP if SSH available)
scp wp-content.tar.gz user@newhost.com:/path/to/wordpress/
WordPress core files don't need to be migrated — the new host already has a clean WordPress installation. Migrating core files sometimes migrates problems (leftover files from old installations, custom core hacks that shouldn't exist).
Step 3: Import the Database
# On new host
wp db import migration.sql
Or via phpMyAdmin: select the database, Import → choose file.
Step 4: Update wp-config.php
The new host has different database credentials. Update wp-config.php:
define('DB_NAME', 'new_database_name');
define('DB_USER', 'new_database_user');
define('DB_PASSWORD', 'new_database_password');
define('DB_HOST', 'internal-db-hostname');
Step 5: Update the Site URL (Critical Step)
Your WordPress database contains the old domain in multiple places. Update it with a search and replace:
# WP-CLI search-replace (the right way to do this)
wp search-replace 'https://oldsite.com' 'https://newsite.com' \
--all-tables \
--precise \
--report-changed-only
Why WP-CLI search-replace, not a SQL query: WordPress stores serialized PHP arrays in the database. Direct SQL REPLACE() breaks serialized data by changing string lengths without updating the length prefixes. WP-CLI's search-replace handles serialized data correctly.
Run this command with the staging URL first (if you're testing on a staging domain before cutting over):
wp search-replace 'https://oldsite.com' 'https://staging.newhost.com' --all-tables --precise
Then run it again when you're ready to go live:
wp search-replace 'https://staging.newhost.com' 'https://oldsite.com' --all-tables --precise
Step 6: Test on Staging
Before the DNS switch, verify everything works:
- [ ] Homepage loads
- [ ] Images load (broken images usually mean the search-replace missed something, or files didn't transfer)
- [ ] Admin login works
- [ ] A post with images loads correctly
- [ ] Contact forms work (may need to reconfigure SMTP settings)
- [ ] WooCommerce: add a product to cart, proceed through checkout (use a test payment gateway)
- [ ] All plugins active and showing no errors (Tools → Site Health)
- [ ] No PHP errors in debug log
Enable WordPress debug mode during testing:
// wp-config.php — enable during testing, disable before going live
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Check /wp-content/debug.log for PHP errors that wouldn't otherwise be visible.
The DNS Cutover
Lower TTL in Advance
DNS changes propagate slowly because of TTL (Time To Live) — the duration DNS resolvers cache your records. Before migration day, lower your TTL to 300 seconds (5 minutes):
- Go to your domain registrar's DNS settings
- Find the A record for your domain
- Change TTL from the default (usually 3600 or 86400 seconds) to 300
- Wait at least as long as the old TTL before making the DNS change
If your old TTL was 86400 seconds (24 hours), you need to wait 24 hours after lowering it before the low TTL is fully propagated. Plan this a day before your migration window.
The Switch
-
Final export and import: Do a fresh database export just before the DNS switch to capture any content changes made during the testing period. Import it to the new host and run search-replace with the real domain.
-
Update DNS: Change the A record for your domain (and
wwwsubdomain if applicable) to point to the new host's IP address. -
Set both old and new host to live: Leave the old host running after the DNS change. DNS propagation takes time — some visitors will still hit the old host for up to 5 minutes (given your lowered TTL). Having the old site still functional prevents errors for those visitors.
-
Monitor: Watch your new host's access logs and error logs immediately after the DNS change. You'll see traffic shift from zero to real visitors within minutes.
-
Keep old host active for 48 hours: Even with a low TTL, some DNS resolvers cache aggressively. Keep the old hosting active for at least 48 hours after the DNS change.
Common Migration Problems and Fixes
Broken Images After Migration
Symptom: Images show as broken, but posts and pages load.
Cause 1: wp-content/uploads didn't transfer completely.
# Check files transferred
ls -la wp-content/uploads/
# Compare directory sizes between old and new host
Cause 2: Search-replace missed image URLs that were stored with http instead of https (or vice versa).
wp search-replace 'http://oldsite.com' 'https://newsite.com' --all-tables --precise
White Screen of Death After Migration
Symptom: Site loads a blank white page. Admin is also blank.
Cause: PHP error that's suppressed with error display off.
# Check error log
tail -f /var/log/php-fpm/error.log
# Or enable WordPress debug temporarily
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw
# Then check wp-content/debug.log
Most common causes:
- Plugin incompatible with new PHP version
- Memory limit too low on new host
- Database credentials wrong in wp-config.php
Mixed Content Warnings
Symptom: Site loads but browser shows "Not Secure." Assets load over HTTP even though site is HTTPS.
Cause: Hard-coded HTTP URLs in database that search-replace missed, or plugin storing absolute URLs.
# Find remaining http references
wp db query "SELECT option_name, option_value FROM wp_options WHERE option_value LIKE '%http://oldsite.com%'"
Install Really Simple SSL plugin temporarily to force HTTPS across the board, then find and fix the root cause.
WooCommerce Orders/Products Missing
Symptom: WooCommerce loads but order history or products are missing.
Cause: Incomplete database import — the SQL file was truncated during import, or some tables weren't included in the export.
# Check table count
wp db tables | wc -l
# Compare with old host table count
# WooCommerce adds ~20 tables to WordPress's default ~12
Re-export with --all-tables explicitly and reimport.
404 Errors on All Posts
Symptom: Homepage loads, but clicking any post or page returns a 404.
Cause: Permalink structure not configured on new host, or .htaccess missing/wrong.
# Regenerate .htaccess
wp rewrite flush --hard
Or in the WordPress admin: Settings → Permalinks → Save Changes (without changing anything).
Email Configuration After Migration
WordPress sends emails via PHP's mail() function by default. On most cloud/container hosts, outbound email from mail() is blocked or heavily filtered. After migration:
- Install WP Mail SMTP or Post SMTP plugin
- Configure SMTP credentials (Mailgun, SendGrid, Postmark, or your own SMTP server)
- Send a test email from the plugin's test interface
- Check your contact forms and WooCommerce order confirmation emails work
Email is the most commonly broken thing after a migration that "worked" — it's worth testing explicitly.
Post-Migration Cleanup
Once the migration is stable and you've confirmed everything works:
# Flush all caches on new host
wp cache flush
wp rewrite flush
# Clear page cache if using a caching plugin
wp w3-total-cache flush all # W3 Total Cache
wp super-cache flush # WP Super Cache
# Regenerate thumbnail sizes (if new host uses different image processing)
wp media regenerate --yes
# Disable debug mode
wp config set WP_DEBUG false --raw
Then cancel your old hosting plan — but not before the 48-hour DNS propagation window has passed.
Using a Migration Plugin
If you're not comfortable with command-line migration, All-in-One WP Migration and Duplicator Pro automate most of this process. Key considerations:
- Free tiers of migration plugins typically limit export size to 512MB or less — insufficient for sites with large media libraries
- Always do a manual database backup before running a migration plugin, regardless of what the plugin promises
- Migration plugins handle the search-replace automatically, but verify it worked correctly with a manual check after
- Some migration plugins struggle with non-standard table prefixes or multisite installations
The manual method described above gives you more control and visibility into what's happening at each step. For straightforward migrations, either approach works.
Get WordPress Hosting That Actually Performs
Isolated containers, git deployment, CLI management, and auto-SSL. No plugin restrictions, no visit limits.
Start WordPress FreeGet WordPress Hosting That Actually Performs
Isolated containers, git deployment, CLI management, and auto-SSL. No plugin restrictions, no visit limits.
Start WordPress FreePowered by WHMCompleteSolution