SiteShift

How to move a WordPress site from WP Engine to Hostinger (2026)

· 6 min read · by Lennart de Ridder

In August 2026 we moved five client sites from WP Engine to Hostinger in one week. None of them had downtime, two of them nearly did, and the reasons had nothing to do with WordPress. This is the order of operations we ended up with, including the parts the hosts’ own guides leave out.

Who this is for. You have a working site at WP Engine, a plan at Hostinger, and you’d like the domain to point at the new place without an afternoon of “why is the site down”. Budget about two hours per site, most of it waiting.

Before you copy anything

Three things to read first, because each of them changes a later step.

The DNS zone. Export or screenshot the complete zone at your registrar before touching it. You need to know which records belong to the website (A and CNAME for the apex and www) and which belong to mail (MX, DKIM selectors, DMARC, autodiscover). Only the web records move. With DMARC on p=reject you don’t get an error when you break mail — it just stops arriving.

The SPF record. This one is easy to miss because it looks like a mail record, and it is — but on three of our five domains the WP Engine IP was baked into it. There are two ways that goes wrong. A hard ip4:<old IP> means that after the move the new server is not allowed to send, so contact-form mail disappears silently. An a or mx mechanism means the new IP is allowed automatically — on shared hosting, that’s the entire machine, other tenants included. Aim for an SPF that names the mail provider (Microsoft 365, a transactional service) and not the hosting IP at all.

DNSSEC. Hostinger’s connection wizard pushes you towards “change your nameservers to ours”. If DNSSEC is on, don’t. The DS record at your registry belongs to your current DNS provider’s key; switching nameservers means the new provider signs with a different key and every validating resolver returns SERVFAIL for the whole domain, web and mail. Pick the “connect via DNS records” tab instead and leave DNS where it is.

Getting the site out of WP Engine

WP Engine gives you an SSH gateway, but it’s a sandbox, not a server. From its documented tool list you get WP-CLI, the MySQL client, bash, rsync, scp, vim and Composer. Two things you’ll reach for aren’t there: tar isn’t in the documented list, and SFTP goes through separate SFTP accounts with their own credentials rather than the gateway. There’s a ten-minute inactivity timeout and a limit of five concurrent connections per user, and only /sites/<environment>/ persists between sessions.

What works:

  1. Get a database dump. Either download a backup point from the WP Engine User Portal (it contains the database as SQL) or, if mysqldump is present on your gateway, run wp db export /sites/<env>/export.sql there. Check the table prefix in wp-config.php — it is not always wp_.
  2. Pull the files with rsync from the gateway to your machine. One long rsync is fine; a hundred small SFTP transfers hit the connection limit.
  3. Check the size of wp-content/uploads before you start. A few gigabytes over rsync is normal; it’s the ten-minute idle timeout you have to avoid, not a size limit.
# from your machine, after `ssh` works against the gateway
rsync -avz --exclude 'wp-content/mu-plugins/' 
  <env>@<env>.ssh.wpengine.net:sites/<env>/ ./site/

The exclusion of mu-plugins is deliberate. Keep reading.

The WP Engine layer that comes along for the ride

A migration copies wp-content literally, including must-use plugins and drop-ins that only make sense at the old host. On every one of our five sites the same eleven items came along: wpengine-common/, mu-plugin.php, the sign-on plugin, the cache plugin, the update-source selector, a security auditor, and a force-strong-passwords pair. Plus wp-content/object-cache.php, a drop-in that points at a cache backend which doesn’t exist on the new host.

That drop-in is the expensive one. It loads before any plugin, fails on every wp_cache_get(), and the failures scale with the number of cache calls — a WooCommerce site with 24 plugins took 4 to 11 seconds per request, a 9-plugin brochure site half a second to a second. The page cache hides it from visitors, so the complaint arrives as “wp-admin is slow”.

Move, don’t delete: make a _wpe-leftovers-<date>/ folder next to public_html and move the mu-plugins, object-cache.php and any 0-byte advanced-cache.php into it. Everything stays restorable, and the client can delete the folder once the site has been fine for a while.

Also check the webroot for backups. .sql dumps, site-archive-*.zip files and whole public_html backup folders are publicly downloadable — a database dump with password hashes and customer data in it. Move them out of the webroot too, even on a site that isn’t live yet; the preview URL is reachable.

Getting it into Hostinger

Hostinger gives you a real shell: SSH on port 65002, user equals your hosting account name, host from hPanel → SSH Access. The webroot for each website is /home/<account>/domains/<domain>/public_html. From here the move is a normal push:

  1. Upload the files (SFTP or rsync over SSH) into that webroot.
  2. Create the database in hPanel and note the credentials; Hostinger prefixes both the database and the user with your account id.
  3. Import the dump: mysql -u <user> -p <db> < export.sql.
  4. Rewrite URLs if the domain or scheme changes — with wp search-replace, never with find-and-replace in the dump. Here’s why.
  5. Update wp-config.php with the new database credentials. Don’t copy the WP Engine one over it.

We do steps 1, 3 and 4 with SiteShift’s push — it backs up whatever database is on the destination first and runs the search-replace on export — but the steps are the same by hand.

The switch

Lower the TTL on the web records a day ahead. Then, in this order and without a coffee break in the middle:

  1. Change the A-record for the apex to the Hostinger IP. For www, Hostinger suggests a CNAME to the apex; at some DNS providers (Hostnet, for one) a CNAME on www is refused because other records already exist on that name. A second A-record to the same IP does the same job with no conflict.
  2. Immediately issue the SSL certificate in hPanel. Let’s Encrypt can only validate the domain once DNS points at the new server, so there is, by definition, a gap. WP Engine also sends HSTS, so your browser will refuse plain http:// during that gap — that’s not DNS being wrong, it’s the certificate not being there yet.
  3. Install and enable the LiteSpeed Cache plugin, then purge it. Requests that arrive in the gap between “DNS points here” and “WordPress serves this domain” get cached as 404s, and those cached 404s look exactly like a broken permalink structure. Purging once, right after the switch, saves you half an hour of flushing permalinks that were never broken.
  4. Send a real message through a contact form and check it arrives. Not a mail from your mail client — those leave through a different path.

Check DNS with a resolver that isn’t yours: https://dns.google/resolve?name=<domain>&type=A. If that shows the new IP and the site still errors, it’s the certificate or the cache, not the record.

Afterwards

Keep WP Engine running for a week. Everything above is reversible as long as it does. Then cancel, and only then clean up the SPF record if you used a temporary ip4: entry for the new server.

And for the next site: the copy-out, push-in and search-replace part is the piece worth automating. It’s why the push in SiteShift is add-only, backs up the destination database first and rewrites URLs on export — the DNS and mail parts stay yours, because they should.

L
Lennart de Ridder

Builds SiteShift and runs DeveloKey, a WordPress agency in Leiden. Every guide here comes from running client sites through the same tool.

Local WordPress with bundled PHP and MySQL, pushed to any host over SSH.

Get SiteShift — €9/mo