DEV Community

Cover image for Moving Hosts? Test Every Page on the New Server Before You Change DNS
Pro Gineous
Pro Gineous

Posted on Originally published at blog.progineous.com

Moving Hosts? Test Every Page on the New Server Before You Change DNS

The scary part of moving a site to a new host isn't copying the files. It's the moment you change the DNS record and hope. If something on the new server is broken, visitors find it before you do, and rolling back takes as long as the TTL says it does.

You don't have to guess. Your own computer can talk to the new server under the real domain name while everyone else still sees the old one, so you can check pages, certificate, forms and redirects first and switch only when both copies match.

Lower the TTL a day or two early

The TTL on your A record decides how long resolvers keep the old answer after you change it. Check it first:

dig +noall +answer example.com A
dig +noall +answer example.com A @ns1.your-dns-host.com```
{% endraw %}
The first asks your normal resolver, where the TTL counts down as the cached copy ages. The second asks the authoritative server and shows the full value. If it says 86400 (one day) or 14400, lower it to 300 in your DNS panel, then wait at least the old TTL before you plan the switch. Resolvers that cached the record yesterday will hold it for the full old value, no matter what you set today. If you're unsure which line of {% raw %}`dig` output is which, we wrote a guide on [how to read dig output](https://blog.progineous.com/read-dig-output-dns/), and the reasons changes sometimes seem stuck are in [how long DNS changes take](https://blog.progineous.com/how-long-dns-changes-take/).

![Diagram of a host move in four steps: lower the A record TTL to 300 a day or two before, test the new server with site-compare.sh while only you can see it, change the A record on switch day and retire the old server a few days later, with two bars showing when the old and the new server serve visitors](https://blog.progineous.com/wp-content/uploads/2026/10/test-website-before-changing-dns-timeline.png)

## Test website before changing DNS, page by page

With the files and database copied over (the full order of steps is in our [step by step migration guide](https://blog.progineous.com/how-to-migrate-a-website/)), point your own machine at the new server. There are two ways, and you'll probably use both.

### One request at a time with curl --resolve

{% raw %}`curl --resolve`{% endraw %} tells curl which IP to use for a name, for that one command only. The URL, the SNI name and the Host header all stay the same, so you're testing the real virtual host:



```bash
curl -sI --resolve example.com:443:203.0.113.20 https://example.com/
curl -sI --resolve example.com:443:203.0.113.10 https://example.com/
Enter fullscreen mode Exit fullscreen mode

Run it against the old IP and the new IP and compare the status line, the location header on redirects, and headers your app sets.

Clicking around with the hosts file

For a real browser session, add a line to your hosts file (/etc/hosts on Linux and macOS, C:\Windows\System32\drivers\etc\hosts on Windows):

203.0.113.20  example.com www.example.com
Enter fullscreen mode Exit fullscreen mode

Now your browser loads the new server. Log in to the admin area (on WordPress that's /wp-login.php), open a few posts, run a search, try the cart. Put a test HTML comment on the new copy so you always know which server you're looking at, and remove the hosts line when you're done.

Check the certificate on the new IP

A page can load fine over HTTP and still fail for visitors because the new server has no valid certificate for your name yet. Ask the new IP for its certificate with the right server name:

openssl s_client -connect 203.0.113.20:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
Enter fullscreen mode Exit fullscreen mode

Look for your domain in the subject and an expiry date well ahead. Without -servername many servers return a default certificate, which tells you nothing. One catch with Let's Encrypt: the usual HTTP challenge can't pass on the new server while DNS still points at the old one. You can copy the existing certificate across, use a DNS challenge, or plan to issue it right after the switch. Our post on checking certificate expiry from the command line covers reading that output.

Compare every URL, not just the home page

The home page is rarely what breaks. It's the old link that used to redirect, a contact page that throws an error, a category page that comes back half empty. To catch those, take every URL from the sitemap and request each one from both servers:

curl -s https://example.com/sitemap.xml | grep -o '<loc>[^<]*' | sed 's/<loc>//' > urls.txt
while read -r u; do
  o=$(curl -s -o /dev/null -w '%{http_code}' --resolve example.com:443:203.0.113.10 "$u")
  n=$(curl -s -o /dev/null -w '%{http_code}' --resolve example.com:443:203.0.113.20 "$u")
  [ "$o" = "$n" ] || echo "$o $n $u"
done < urls.txt
Enter fullscreen mode Exit fullscreen mode

On WordPress the sitemap at /sitemap.xml is often an index that lists smaller sitemaps, so you may need to repeat the first step for each of those. Status codes alone miss pages that return 200 with the wrong content, so compare the title and response size too.

That's exactly what our site-compare script does. Give it the new IP, optionally the old one (otherwise it uses whatever public DNS returns), and a list of URLs as arguments, from a file with -f, or from a sitemap with --sitemap:

./site-compare.sh --old 203.0.113.10 --new 203.0.113.20 \
  --sitemap https://example.com/sitemap.xml https://example.com/wp-login.php
Enter fullscreen mode Exit fullscreen mode

It reads the sitemap from the old side and follows a sitemap index one level down. For each URL it sends the same GET request to both servers with curl --resolve, does not follow redirects, and lines up status code, redirect target, page title and response size. Size differences above 15 percent get flagged (change that with -t). It checks the certificate once per host on each side first, and if one fails to verify it skips those pages unless you pass -k. The exit code is 0 when everything matches, 1 when it finds differences and 2 on errors, so it fits in a script too.

Terminal screenshot of site-compare.sh comparing example.com on an old and a new server from its sitemap: the certificate is ok on both, five URLs are OK and three are DIFF (the pricing page is 43 percent smaller, the contact page returns 500 on the new server and the old-pricing redirect is missing there), ending with 3 of 8 URLs differ and exit code 1

In that run the redirect from /old-pricing/ is gone on the new server, which usually means rewrite rules didn't come along (common when moving from Apache to nginx, which ignores .htaccess). The contact page returns 500, and the pricing page is 43 percent smaller, which on a real site points to a missing plugin, PHP extension or include. Each of those would have reached visitors on switch day.

The parts a page check won't see

Some things only show up when you test them on purpose:

  • Forms and outgoing email. Submit every form on the new server and confirm the message arrives. If the site sends mail itself, the new IP may need to be in your SPF record, or the mail goes to spam.
  • Cron jobs. Run crontab -l on the old server and recreate the jobs. On WordPress, check that WP-Cron or the system cron replacing it is running.
  • Hardcoded addresses. Search config files and the database for the old IP or paths.
  • Other DNS records. If you only change the A record, mail (MX) and other records stay put. If you move name servers too, recreate every record first and compare them with dig.
  • WordPress specifics. PHP version, file permissions on uploads, and caching plugins that stored the old server path are the usual suspects. Our guide on moving a WordPress site safely goes through them.

Checklist titled Before you change DNS with ten ticked items: TTL lowered to 300, every sitemap URL matches, certificate valid on the new IP, old redirects still work, forms send and email arrives, cron jobs recreated, admin login works, other DNS records copied, hosts file line removed and old server stays on

Switch, then keep the old server running

When the comparison comes back clean, change the A record (and www if it's a separate record). With a 300 second TTL most visitors move within minutes. Check from the outside with dig +short example.com against a couple of public resolvers, watch the access log on the new server fill up, and load the site with a plain curl -s https://example.com/ | grep for the test comment you left, so you know public DNS now lands on the new copy.

Keep the old server online for a few days. Some resolvers hold records longer than they should, and if something goes wrong, pointing the record back is a one line change. Once traffic on the old server drops to nothing, put the TTL back to a normal value like 3600 and shut the old server down.

The script is free and read only, it sends GET requests and changes nothing. You can grab site-compare.sh from our server toolkit on GitLab. And if you're still deciding where the site should live next, Pro Gineous has VPS plans from $6.96/mo.

FAQ

Can you test a site on a new server without editing the hosts file?

Yes. curl --resolve example.com:443:NEW_IP https://example.com/ sends one request to the new server under the real name. You only need the hosts file to click through the site in a browser.

How far ahead should you lower the TTL?

At least as long as the current TTL. If the record has a TTL of 86400, lower it to 300 a full day before the switch, so every cached copy has expired by the time you change the IP.

Why does the new server show the wrong certificate?

Usually it has no certificate for your name yet, or you connected without the server name. Test with openssl s_client -servername example.com. With Let's Encrypt, copy the current certificate or use a DNS challenge, since the HTTP challenge can't pass before the switch.

Originally published on the Pro Gineous blog.

Top comments (0)