---
title: "How I Moved a 50,000 Visitor/Month WordPress Site to Cloud Hosting Without Downtime"
description: The shared hosting account was buckling. Page load times had crept from 800ms to over 3 seconds during peak hours. The CPU throttling kicks were visible in the logs. The host's dashboard…
url: "https://hostingguider.com/guides/migrate-wordpress-cloud-hosting-no-downtime/"
date: "2026-06-02T10:13:32+00:00"
modified: "2026-06-02T10:18:16+00:00"
author: Rantideb Howlader
type: article
site: HostingGuider
language: en-US
---

# How I Moved a 50,000 Visitor/Month WordPress Site to Cloud Hosting Without Downtime

The shared hosting account was buckling.

Page load times had crept from 800ms to over 3 seconds during peak hours. The CPU throttling kicks were visible in the logs. The host’s dashboard showed my account flagged for resource overuse three times in two weeks. The server was shared with hundreds of other sites and during busy periods, all of them competed for the same CPU and RAM.

With 50,000 monthly visitors, the site had outgrown shared hosting. The move to cloud hosting was inevitable. But going offline during the migration was not an option. Google tracks downtime. Readers stop trusting sites that throw errors. Revenue from ad placements and affiliate links stops the moment the site goes dark.

This guide covers every step of that migration. No downtime. No lost data. No angry readers.

The target was [Cloudways](https://hostingguider.com/recommend/cloudways) running on DigitalOcean infrastructure. The same process works for any cloud VPS migration.

Table of Contents

## What You Will Need

Before starting, gather these details from your current host:

| Item | Where to Find It |
| --- | --- |
| Current server IP address | Hosting dashboard or `dig +short yourdomain.com` |
| Current PHP version | Hosting dashboard or `php -v` |
| Database name | wp-config.php (DB_NAME) |
| Database username | wp-config.php (DB_USER) |
| Database password | wp-config.php (DB_PASSWORD) |
| WordPress root path | cPanel File Manager or `pwd` in WordPress directory |
| Total site size | `du -sh /path/to/wordpress/` |
| Active plugins list | WordPress admin, Plugins, Active |
| Current WordPress version | WordPress admin, Dashboard |

Write all of these down. You will reference them throughout the migration.

## The Zero-Downtime Strategy

Here is what makes this migration invisible to visitors.

Visitors find your site through DNS. DNS translates your domain name into an IP address. When you change hosting, you change that IP address. Visitors who looked up the old IP keep going to the old server. Visitors who look up the new IP go to the new server.

DNS changes propagate globally over 1-48 hours. During that window, different visitors go to different servers. Both servers must serve the same content.

The strategy has three phases:

**Phase 1 (days before):** Lower your DNS TTL so the propagation window is short. Start syncing your site to the new server.

**Phase 2 (migration day):** Do a final sync. Switch DNS. Both servers serve the same content for about an hour.

**Phase 3 (after):** Monitor the new server. Keep the old server live for 48 hours before cancelling.

The result is a migration where no visitor ever sees downtime. The old server serves requests until the new one takes over. The handover is invisible.

![zero downtime website migration timeline infographic](https://hostingguider.com/wp-content/uploads/2026/06/website-migration-timeline-1-1024x512.webp)

*A typical zero-downtime migration timeline*

## Phase 1: Preparation (Three Days Before Migration)

### Step 1: Audit Your Current Site

Before touching anything, document exactly what you have.

**Check total site size:**

SSH into your current hosting or use cPanel file manager. Run:

```
du -sh ~/public_html/
```

Or wherever your WordPress lives. A 50,000 visitor/month site typically has between 2GB and 15GB of content. This affects how long the transfer takes.

**Check PHP version:**

```
php -v
```

Write down the exact version (e.g., PHP 8.1.12). Your new server must match this exactly.

**Check WordPress version and active plugins:**

Log into WordPress admin. Go to Dashboard, then Updates. Note the WordPress version.

Go to Plugins, then Active. Take a screenshot or export the list. You need to verify every plugin works on the new server.

**Check for custom server configurations:**

Some plugins and themes require specific server configurations. Check for any `.user.ini` or `.htaccess` customisations that might not transfer automatically:

```
cat ~/public_html/.htaccess
```

Save the content of this file. You will need it later.

**Check current server response time:**

```
curl -w "\n DNS: %{time_namelookup}\n Connect: %{time_connect}\n TTFB: %{time_starttransfer}\n Total: %{time_total}\n" -o /dev/null -s https://yourdomain.com
```

Save these numbers. They are your baseline for comparing performance after migration.

### Step 2: Choose and Provision Your New Cloud Server

For a 50,000 visitor/month WordPress site, the minimum server specification is:

| Resource | Minimum | Recommended |
| --- | --- | --- |
| CPU | 2 vCPU | 4 vCPU |
| RAM | 2GB | 4GB |
| Storage | 30GB | 50GB |
| Storage type | SSD | NVMe SSD |
| Bandwidth | 2TB | 4TB |

On [Cloudways](https://hostingguider.com/recommend/cloudways), this maps to the DigitalOcean Premium plan at approximately $22-42 per month. The Premium tier includes NVMe storage, which delivers dramatically better WordPress database performance than standard SSD.

Alternative options if you prefer self-managed VPS: [Hostinger VPS](https://hostingguider.com/recommend/hostinger) and [Contabo](https://hostingguider.com/recommend/contabo) both offer competitive plans at this specification level.

**Provision the server now, not on migration day.** Give yourself time to configure it properly without rush.

### Step 3: Set Up the New Server Environment

The new server must match the old server’s PHP version exactly before you move any files.

If using Cloudways, their platform lets you select PHP version during WordPress application creation. Match it to what you documented in Step 1.

If using a self-managed VPS, install the exact PHP version:

```
sudo apt install php8.1 php8.1-mysql php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-xmlrpc php8.1-soap php8.1-intl php8.1-zip php8.1-imagick php8.1-redis -y
```

Install a web server (Nginx) and database (MariaDB):

```
sudo apt install nginx mariadb-server -y
```

Create the database on the new server:

```
sudo mariadb
```

```
CREATE DATABASE wordpress_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'strong_new_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```

Write down:

- New server IP address
- New database name
- New database username
- New database password

### Step 4: Lower Your DNS TTL

This is the most important preparation step. Do it now, not on migration day.

Your DNS records have a TTL value. TTL stands for Time to Live. It tells DNS servers how long to cache your IP address before checking again.

The default TTL is often 3600 seconds (1 hour) or 86400 seconds (24 hours). When you change your DNS to point to the new server, propagation takes as long as the TTL allows.

**Lower it now to 300 seconds (5 minutes).**

Log into your domain registrar. Find your DNS settings. Find the A record for your domain. Change the TTL from whatever it is now to 300.

Wait 24 hours after lowering the TTL before proceeding. This ensures every DNS server in the world has seen the new short TTL. Now when you switch DNS on migration day, propagation completes in about 5 minutes instead of hours.

Verify your TTL has propagated:

```
dig yourdomain.com | grep TTL
```

The number after the domain name in the output should be 300 or close to it.

## Phase 2: Initial Site Clone (Day Before Migration)

### Step 5: Set Up SSH Key Access to the New Server

You need to transfer files between servers. SSH key authentication between the two servers makes this fast.

On your OLD server, check if it has an SSH key:

```
ls ~/.ssh/id_rsa.pub
```

If the file exists, show the public key:

```
cat ~/.ssh/id_rsa.pub
```

If it does not exist, generate one:

```
ssh-keygen -t ed25519 -C "migration-key"
```

Press Enter to accept defaults. Then show the public key:

```
cat ~/.ssh/id_ed25519.pub
```

Copy this entire line. Log into the NEW server and add this key:

```
mkdir -p ~/.ssh
echo "PASTE_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
```

Test the connection from the OLD server:

```
ssh -i ~/.ssh/id_ed25519 root@NEW_SERVER_IP
```

If it connects without asking for a password, the key setup is correct. Type `exit` to return to the old server.

### Step 6: Export the Current Database

On your OLD server, create a full database backup:

```
mysqldump \
  --user=DB_USERNAME \
  --password=DB_PASSWORD \
  --single-transaction \
  --quick \
  --lock-tables=false \
  --add-drop-table \
  DATABASE_NAME > /tmp/wordpress-initial.sql
```

Replace DB_USERNAME, DB_PASSWORD, and DATABASE_NAME with your actual values.

The `--single-transaction` flag is critical. It creates a consistent snapshot without locking tables. Your site stays live during the export.

Check the export file was created and has a reasonable size:

```
ls -lh /tmp/wordpress-initial.sql
```

Compress it to speed up transfer:

```
gzip /tmp/wordpress-initial.sql
```

You now have `/tmp/wordpress-initial.sql.gz`.

### Step 7: Transfer the Database to the New Server

From your OLD server, push the database file to the new server:

```
scp /tmp/wordpress-initial.sql.gz root@NEW_SERVER_IP:/tmp/
```

SSH into the new server:

```
ssh root@NEW_SERVER_IP
```

Decompress and import:

```
gunzip /tmp/wordpress-initial.sql.gz
mysql -u wp_user -p wordpress_db < /tmp/wordpress-initial.sql
```

Enter the new database password when prompted.

Verify the import succeeded:

```
mysql -u wp_user -p wordpress_db -e "SHOW TABLES;" | wc -l
```

This counts the tables. Compare with your old server:

```
# On old server:
mysql -u DB_USERNAME -p DATABASE_NAME -e "SHOW TABLES;" | wc -l
```

The numbers should match.

### Step 8: Sync WordPress Files to the New Server

Use rsync to copy all WordPress files. rsync only copies changed files on subsequent runs, making the final sync on migration day fast.

On the OLD server, run:

```
rsync -avzP \
  --exclude="*.log" \
  --exclude="wp-content/cache/*" \
  --exclude="wp-content/backups/*" \
  --exclude=".git" \
  -e "ssh -i ~/.ssh/id_ed25519" \
  ~/public_html/ \
  root@NEW_SERVER_IP:/var/www/yourdomain.com/
```

Breaking down the flags:

- `-a`: Archive mode (preserves permissions, timestamps, symlinks)
- `-v`: Verbose (shows what is being transferred)
- `-z`: Compress during transfer (faster for large files)
- `-P`: Show progress and resume if interrupted
- `--exclude`: Skip these directories (cache, logs, backups are not needed)

For a 5GB site on a 1 Gbps connection, this takes 5-15 minutes. For a 15GB site, expect 30-60 minutes.

When the transfer finishes, verify the file count matches:

```
# On old server
find ~/public_html -type f | wc -l

# On new server
find /var/www/yourdomain.com -type f | wc -l
```

Numbers should be very close (some excluded files reduce the count slightly).

### Step 9: Configure WordPress on the New Server

On the NEW server, edit wp-config.php to use the new database credentials:

```
nano /var/www/yourdomain.com/wp-config.php
```

Update these lines:

```
define('DB_NAME', 'wordpress_db');
define('DB_USER', 'wp_user');
define('DB_PASSWORD', 'strong_new_password');
define('DB_HOST', 'localhost');
```

Also update the WordPress site URL to use the new server IP temporarily for testing:

The URLs in the database still point to your domain. You will test using the hosts file trick instead. Do not change the database URLs yet.

Save and exit.

### Step 10: Set Correct File Permissions

```
sudo chown -R www-data:www-data /var/www/yourdomain.com
sudo find /var/www/yourdomain.com -type d -exec chmod 755 {} \;
sudo find /var/www/yourdomain.com -type f -exec chmod 644 {} \;
sudo chmod 640 /var/www/yourdomain.com/wp-config.php
```

### Step 11: Configure the Web Server

If using Cloudways, the Nginx configuration is handled automatically through their dashboard.

If using a self-managed VPS, configure Nginx:

```
sudo nano /etc/nginx/sites-available/yourdomain.com
```

Paste a standard WordPress Nginx configuration:

```
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/yourdomain.com;
    index index.php index.html;

    client_max_body_size 64M;
    access_log /var/log/nginx/yourdomain.com-access.log;
    error_log /var/log/nginx/yourdomain.com-error.log warn;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_read_timeout 300;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|webp)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    location ~ /\.(?!well-known) {
        deny all;
    }
}
```

Enable the site:

```
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```

### Step 12: Test the New Site Using Hosts File

Before changing DNS, verify the new server serves your site correctly. The hosts file trick routes your local computer to the new server without affecting anyone else.

**On Windows**, open Notepad as Administrator. Open the file `C:\Windows\System32\drivers\etc\hosts`.

**On Mac or Linux**, open a terminal and run:

```
sudo nano /etc/hosts
```

Add this line at the bottom:

```
NEW_SERVER_IP yourdomain.com www.yourdomain.com
```

Replace NEW_SERVER_IP with the actual IP of your new server.

Save the file.

Now open your browser and visit `https://yourdomain.com`. You are now seeing the new server even though DNS has not changed. Nobody else is affected.

Test everything thoroughly:

- Home page loads correctly
- Internal links work
- Images display
- Contact forms submit
- If WooCommerce: add a product to cart and simulate checkout
- If a membership site: log in with an existing account
- Check that WordPress admin (`/wp-admin`) works

If anything is broken, fix it now before proceeding.

When done testing, remove the hosts file entry:

```
sudo nano /etc/hosts
```

Delete the line you added. Save. Your browser returns to the old server.

## Phase 3: SSL Certificate on New Server

### Step 13: Install SSL Certificate

Your old server had an SSL certificate. The new server needs one too before you switch DNS.

The challenge is that Let’s Encrypt verifies domain ownership by checking a file at your domain’s current IP. Before switching DNS, your domain still points to the old server.

**Option A: Use a certificate from your hosting provider.**

Cloudways and most managed platforms provide a one-click SSL through Let’s Encrypt. It verifies using a different method that does not require the domain to point to their server yet (DNS verification). Use this if available.

**Option B: Get the certificate after DNS switch.**

Switch DNS, wait for it to propagate (about 5 minutes with TTL=300), then immediately install Certbot:

```
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
```

This option means your site is briefly on HTTP after DNS switch. The window is 5-15 minutes. For most content sites, this is acceptable. For ecommerce, use Option A.

**Option C: Pre-stage with a different domain.**

Create a subdomain like `staging.yourdomain.com` that points to the new server IP. Install Certbot for that subdomain. After DNS switch, add the main domain to the certificate:

```
sudo certbot certonly --nginx -d yourdomain.com -d www.yourdomain.com
```

## Phase 4: Migration Day — The Final Sync and DNS Switch

### Step 14: Calculate the Migration Window

Choose a time with your lowest traffic. For most sites, this is between 2am and 5am in the timezone of your primary audience.

Check your Google Analytics or analytics tool for hourly traffic patterns. Identify the 2-hour window with the least visitors. That is your migration window.

### Step 15: Final File Sync

On migration day, run rsync again. This time it only transfers files changed since Step 8:

```
rsync -avzP \
  --exclude="*.log" \
  --exclude="wp-content/cache/*" \
  --exclude="wp-content/backups/*" \
  --delete \
  -e "ssh -i ~/.ssh/id_ed25519" \
  ~/public_html/ \
  root@NEW_SERVER_IP:/var/www/yourdomain.com/
```

The `--delete` flag removes files from the new server that no longer exist on the old server. This ensures the two directories are identical.

This sync is much faster than the initial one because only recent changes transfer. For an active blog, this typically transfers 50-500 files in under two minutes.

### Step 16: Enable Maintenance Mode on the Old Site

This is the only visible action in the entire migration. It lasts 5-10 minutes.

Put WordPress into maintenance mode on the OLD server. The cleanest way is with WP-CLI:

```
# On old server, in the WordPress directory
wp maintenance-mode activate
```

If WP-CLI is not available, create the file manually:

```
echo '<?php $upgrading = time(); ?>' > ~/public_html/.maintenance
```

Visitors now see the WordPress maintenance page. This is intentional. During this short window, all new writes (comments, form submissions, orders) stop. You take the final database snapshot with no new data being written.

### Step 17: Take the Final Database Snapshot

With maintenance mode active, no new data is being written. Take the definitive final snapshot:

```
mysqldump \
  --user=DB_USERNAME \
  --password=DB_PASSWORD \
  --single-transaction \
  --quick \
  --lock-tables=false \
  --add-drop-table \
  DATABASE_NAME | gzip > /tmp/wordpress-final.sql.gz
```

Transfer it immediately:

```
scp /tmp/wordpress-final.sql.gz root@NEW_SERVER_IP:/tmp/
```

### Step 18: Import Final Database on New Server

SSH into the new server:

```
ssh root@NEW_SERVER_IP
```

Import the final database:

```
gunzip /tmp/wordpress-final.sql.gz

# First, drop existing tables to ensure clean import
mysql -u wp_user -p wordpress_db -e "SET FOREIGN_KEY_CHECKS = 0; SET GROUP_CONCAT_MAX_LEN=32768; SET @tables = NULL; SELECT GROUP_CONCAT('\`', table_name, '\`') INTO @tables FROM information_schema.tables WHERE table_schema = (SELECT DATABASE()); SET @tables = IFNULL(@tables,'x'); SET @stmt = CONCAT('DROP TABLE IF EXISTS ', @tables); PREPARE stmt1 FROM @stmt; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; SET FOREIGN_KEY_CHECKS = 1;"

mysql -u wp_user -p wordpress_db < /tmp/wordpress-final.sql
```

Verify the import:

```
mysql -u wp_user -p wordpress_db -e "SELECT COUNT(*) FROM wp_posts WHERE post_status='publish';"
```

Compare this number with the same query on the old server. They should match exactly.

### Step 19: Clear All Caches on New Server

Before switching DNS, clear every cache on the new server so fresh content is served:

If using Cloudways:

- Go to the application in Cloudways dashboard
- Click Manage, then Varnish, then Clear

If using self-managed:

```
# If using Redis object cache
redis-cli FLUSHALL

# If using Nginx FastCGI cache
sudo rm -rf /var/cache/nginx/*

# If W3 Total Cache or WP Super Cache:
wp cache flush
```

### Step 20: Switch DNS

This is the moment of switchover. The action itself takes under 10 seconds. The propagation completes in 5 minutes with TTL=300.

Log into your domain registrar. Go to DNS settings. Find the A record for your domain.

Change the IP address from OLD_SERVER_IP to NEW_SERVER_IP.

| Record | Old Value | New Value |
| --- | --- | --- |
| @ (root domain) | OLD_SERVER_IP | NEW_SERVER_IP |
| www | OLD_SERVER_IP | NEW_SERVER_IP |

Save the changes.

### Step 21: Deactivate Maintenance Mode on the New Server

The new server is now the primary. Remove maintenance mode:

```
# On new server via SSH
cd /var/www/yourdomain.com
rm -f .maintenance

# Or via WP-CLI
wp maintenance-mode deactivate
```

### Step 22: Verify DNS Has Propagated

Check that DNS is resolving to the new server:

```
dig +short yourdomain.com
```

Compare the output IP against your new server IP. When they match, propagation is complete for your local DNS resolver.

Check from multiple locations using:

```
curl https://dnschecker.org/api/dns/yourdomain.com/A?1
```

Or visit [DNS Checker](https://dnschecker.org/?utm_source=hostingguider.com) and enter your domain. It shows the current DNS resolution from dozens of locations worldwide.

Propagation is complete when all locations show the new IP.

### Step 23: Run a Final Test from Outside Your Network

Use your phone on mobile data (not connected to your home WiFi) to visit the site. Mobile carriers use different DNS resolvers and are often among the first to see DNS changes.

Check:

- Site loads correctly
- HTTPS padlock appears
- No broken images or links
- Speed feels at least as good as before

![DNS propagation verification infographic showing global DNS update timeline](https://hostingguider.com/wp-content/uploads/2026/06/dns-propagation-verification-1024x683.webp)

*How DNS changes propagate across global locations after a server migration*

## Phase 5: Post-Migration Monitoring (48 Hours)

### Step 24: Keep Old Server Running

Do not cancel old hosting yet. For 48 hours, both servers are online.

Visitors whose DNS resolvers have not propagated still reach the old server. The old server is still live. This is intentional. They get a working site.

Monitor old server access logs to see when traffic drops to zero:

```
# On old server
sudo tail -f /var/log/nginx/access.log
```

When the log goes quiet (no new entries for 10+ minutes), propagation is essentially complete.

### Step 25: Monitor New Server in Real Time

On the new server, watch all the key metrics:

**Watch Nginx access log:**

```
sudo tail -f /var/log/nginx/yourdomain.com-access.log
```

Requests should appear immediately. If log is empty after propagation completes, something is wrong.

**Watch error log:**

```
sudo tail -f /var/log/nginx/yourdomain.com-error.log
```

A clean migration shows no errors here.

**Watch resource usage:**

```
htop
```

CPU should stay well under 80%. Memory should stay under 80%. If either is maxing out, you have a performance problem to investigate.

**Check database connectivity:**

```
mysql -u wp_user -p wordpress_db -e "SELECT COUNT(*) FROM wp_posts;"
```

Should return the correct count instantly. Any delay indicates database issues.

### Step 26: Verify All Site Functions

Check these immediately after migration:

- **WordPress admin:** Log in at /wp-admin. Dashboard loads. Plugins show active.
- **Contact forms:** Submit a test contact form. Verify the email arrives.
- **Comments:** Leave a test comment. Verify it appears.
- **Search:** Use the WordPress search. Results appear correctly.
- **Media uploads:** Upload a test image from the admin. It uploads and displays.
- **User logins:** Log out and log back in. Sessions work correctly.
- **RSS feed:** Visit /feed/. Content appears correctly.
- **Sitemap:** Visit your sitemap URL. Google can index from here.

If WooCommerce is active:

- Add a product to cart
- Go through checkout process
- Verify order confirmation email arrives
- Check order appears in admin under WooCommerce, Orders

### Step 27: Check Google Search Console

Log into Google Search Console. Go to Coverage. Check for any new crawl errors.

Submit your sitemap if it was not already submitted:

```
https://yourdomain.com/sitemap.xml
```

Request re-indexing of the home page manually from the URL Inspection tool.

### Step 28: Compare Performance Before and After

Run the same curl timing test from Step 1:

```
curl -w "\n DNS: %{time_namelookup}\n Connect: %{time_connect}\n TTFB: %{time_starttransfer}\n Total: %{time_total}\n" -o /dev/null -s https://yourdomain.com
```

Compare with your baseline. A successful migration to cloud hosting typically shows:

| Metric | Typical Improvement |
| --- | --- |
| TTFB | 40-60% lower |
| Total load time | 30-50% lower |
| p99 latency | 50-70% lower |
| Concurrent capacity | 3-5x higher |

For context on what these numbers mean and what to expect, [the site performance guide](https://hostingguider.com/blog/website-uptime-performance/) explains how server response metrics affect real visitor experience.

## Phase 6: Post-Migration Optimisation

### Step 29: Update WordPress Site URL

The database contains the old server URL. WordPress usually handles this correctly but verify by checking Settings, then General in WordPress admin.

Both WordPress Address and Site Address should show `https://yourdomain.com`.

If they show the old server IP or HTTP instead of HTTPS, update them now.

If you migrated from HTTP to HTTPS, run a URL search-replace:

Install WP-CLI on the new server:

```
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
```

Run the search-replace:

```
cd /var/www/yourdomain.com
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --all-tables
```

Clear all caches after this:

```
wp cache flush
```

### Step 30: Configure Caching on New Server

The new server should have caching configured from day one. Without it, every visitor causes PHP and database processing on every page view.

On Cloudways, enable Varnish caching from the dashboard. It activates with one click and dramatically reduces server load.

For self-managed VPS, install and configure LiteSpeed Cache or WP Rocket:

Install Redis for object caching:

```
sudo apt install redis-server php8.1-redis -y
sudo systemctl enable redis-server
sudo systemctl start redis-server
```

Install the Redis Object Cache plugin in WordPress. Activate it. Enable in plugin settings.

For page caching, WP Super Cache (free) or WP Rocket (paid) serve cached HTML pages without touching PHP or the database for returning visitors. A 50,000 visitor/month site on a well-cached server uses a fraction of the CPU of the same site without caching.

[How caching affects site speed](https://hostingguider.com/blog/caching-website-speed/) covers how each caching layer works and what it saves.

### Step 31: Set Up Automated Backups

Never go 48 hours on a new server without backups.

On Cloudways, automated backups are available from the Application tab. Enable daily backups with 14-day retention.

For self-managed VPS, create the backup script:

```
sudo nano /usr/local/bin/site-backup.sh
```

Paste:

```
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M)
SITE_DIR="/var/www/yourdomain.com"
BACKUP_DIR="/var/backups/yourdomain.com"
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASS="strong_new_password"

mkdir -p $BACKUP_DIR

tar -czf $BACKUP_DIR/files-$DATE.tar.gz -C $SITE_DIR .
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/db-$DATE.sql.gz
find $BACKUP_DIR -mtime +14 -delete

echo "Backup complete: $DATE"
```

```
sudo chmod +x /usr/local/bin/site-backup.sh
sudo crontab -e
```

Add:

```
0 3 * * * /usr/local/bin/site-backup.sh >> /var/log/site-backup.log 2>&1
```

### Step 32: Set Up External Monitoring

Your new server needs monitoring from outside. If the server goes down, you need to know before your readers do.

Set up [UptimeRobot](https://uptimerobot.com/?utm_source=hostingguider.com) free monitoring:

1. Create an account
2. Add a new monitor: HTTP(s) type
3. Enter your domain URL
4. Set check interval to 5 minutes
5. Add your email for notifications

UptimeRobot checks your site every 5 minutes and sends an email if it goes offline. This gives you the alert speed needed to respond before significant traffic is affected.

[Website uptime importance](https://hostingguider.com/blog/website-uptime-importance/) explains what even short downtime costs in real traffic and rankings.

## Phase 7: Old Server Decommission

### Step 33: Monitor Traffic Drop on Old Server

Watch the old server access logs over the next 48 hours:

```
# On old server
sudo tail -f /var/log/apache2/access.log
```

Or wherever your old hosting logs live.

Traffic gradually shifts to the new server as DNS propagates. After 24 hours, most traffic should be on the new server. After 48 hours, the old server should be receiving virtually no traffic.

### Step 34: Final Check Before Cancelling Old Hosting

Before cancelling the old hosting account, verify:

- New server is receiving all traffic (check analytics)
- No error log entries on new server
- All backups are working
- SSL certificate is valid and auto-renewing
- All site functions work as expected
- Email sending works (contact forms, WooCommerce notifications)

Run the same load test from before the migration and compare numbers:

```
wrk -t4 -c50 -d30s --latency https://yourdomain.com/
```

### Step 35: Cancel Old Hosting

Only after 48-72 hours of stable operation on the new server should you cancel the old hosting.

Check the old hosting billing cycle before cancelling. If you are two days into a monthly billing cycle, waiting another 26 days costs you the same money but gives you more safety margin. The old server as an emergency fallback is worth the monthly cost until you are confident in the new setup.

Before cancelling, download a final backup from the old hosting account. Keep this backup locally for at least 30 days.

## What to Do When Things Go Wrong

A migration this size sometimes hits unexpected problems. Here are the most common ones.

### Problem: Site Broken on New Server During Testing

Check the error log first:

```
sudo tail -100 /var/log/nginx/yourdomain.com-error.log
sudo tail -100 /var/log/php_errors.log
```

Most common causes:

- Wrong database credentials in wp-config.php
- Wrong file permissions (fix with `sudo chown -R www-data:www-data /var/www/yourdomain.com`)
- Missing PHP extension (check phpinfo() for the extension)
- Missing .htaccess or incorrect Nginx rewrite rules

### Problem: WordPress URLs Redirect to Old Server

The database still contains the old server IP in the `siteurl` and `home` options.

```
cd /var/www/yourdomain.com
wp option update siteurl 'https://yourdomain.com'
wp option update home 'https://yourdomain.com'
wp cache flush
```

### Problem: Images and Media Not Loading

The uploads folder did not transfer correctly, or the folder permissions are wrong.

```
sudo ls -la /var/www/yourdomain.com/wp-content/uploads/
sudo chown -R www-data:www-data /var/www/yourdomain.com/wp-content/
```

Re-run rsync targeting just the uploads directory:

```
rsync -avzP \
  -e "ssh -i ~/.ssh/id_ed25519" \
  ~/public_html/wp-content/uploads/ \
  root@NEW_SERVER_IP:/var/www/yourdomain.com/wp-content/uploads/
```

### Problem: SSL Certificate Error After DNS Switch

If Let’s Encrypt was not set up before DNS switch, do it immediately after:

```
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
```

Certbot should succeed within 5 minutes of DNS propagation completing.

### Emergency Rollback

If the new server has a critical problem that you cannot fix within 30 minutes after the DNS switch, roll back to the old server:

Change DNS back to OLD_SERVER_IP at your registrar. With TTL=300, rollback propagates in 5 minutes. The old server was never taken offline, so this is always available.

Take the time to diagnose and fix the problem on the new server while the old server handles traffic. Then do the migration again when the new server is confirmed working.

## Full Migration Timeline Summary

| Day | Action |
| --- | --- |
| Day 1 | Audit current site. Document everything |
| Day 1 | Provision new cloud server |
| Day 1 | Lower DNS TTL to 300 seconds |
| Day 2 | Set up new server environment |
| Day 3 | Initial file sync and database transfer |
| Day 3 | Test new site via hosts file |
| Day 3 | Fix any problems found in testing |
| Day 3 | Set up SSL certificate |
| Day 4 (migration night) | Final file sync |
| Day 4 | Enable maintenance mode |
| Day 4 | Final database snapshot and import |
| Day 4 | Switch DNS |
| Day 4 | Disable maintenance mode |
| Day 4 | Verify site on new server |
| Days 5-6 | Monitor new server. Keep old server live |
| Day 7 | Cancel old hosting after stable operation confirmed |

## Frequently Asked Questions

### How long was the actual downtime during this migration?

The maintenance mode window was 8 minutes. This is the only period where visitors saw a maintenance page. Before that window, the old server served all traffic. After that window, the new server served all traffic. DNS propagation with TTL=300 completed in about 12 minutes. During those 12 minutes, both servers served the site correctly to different visitors. Actual visitor-visible downtime was zero.

### What if I do not have SSH access to the old hosting?

Many shared hosts only provide cPanel, not SSH. In that case, use cPanel File Manager to download WordPress files as a ZIP. Use cPanel phpMyAdmin to export the database. Transfer both to the new server. This is slower but produces the same result. If you have a large site (over 2GB), contact your old host about enabling SSH access or use a plugin like Duplicator to create a portable backup.

### Do I need to update any WordPress settings after migration?

Check three things. First, verify WordPress Address and Site Address in Settings, then General both show the correct HTTPS URL. Second, clear all caches (object cache, page cache, CDN cache) to ensure fresh content is served. Third, update any hardcoded server paths in plugins that reference the old server file structure. Most plugins use WordPress functions that resolve correctly automatically.

### Will Google penalise my site for the migration?

No, if done correctly. The site stays live throughout. Search engines treat a server IP change as routine infrastructure maintenance. What Google does care about is actual downtime. Keep the old server live during propagation and Google will not experience an outage. After migration, monitor Google Search Console for crawl errors. Submit the sitemap for re-indexing. Usually rankings are unaffected within 24 hours.

### How do I handle WooCommerce orders during the maintenance window?

For a high-order-volume WooCommerce store, 8 minutes of maintenance mode is significant. Reduce the window further by doing the final database sync without maintenance mode, accepting that a handful of orders during the 2-3 minute sync may be on the old database but not the new one. After DNS switch, immediately check the old server’s WooCommerce order list for any orders placed in the last 10 minutes. Manually recreate those orders on the new server. For very high-volume stores, coordinate a brief window during the lowest order period and communicate maintenance to customers in advance.

### Can I use a plugin like Duplicator instead of manual rsync?

Yes. Duplicator and All-in-One WP Migration both create portable backup packages you can install on a new server. They are easier for beginners than rsync. The tradeoff is that large sites (over 2GB) hit the PHP upload limit and need special handling. They also do not provide the incremental sync capability that rsync does, meaning the final sync window is longer. For a 50,000 visitor/month site in the 2-8GB range, plugins work well. For larger sites, rsync gives more control.

### How do I know if my new server is handling the traffic properly?

Watch `htop` for the first few hours after migration. CPU should stay under 60% during normal periods. RAM should stay under 70%. Check the Nginx access log to confirm requests are landing on the new server. Run a load test from a separate machine to confirm the server handles concurrent load. If anything looks concerning, the old server is still live as a fallback while you diagnose.