Migrating a shop is different from migrating a website in one respect that governs everything else: the data keeps changing while you move it. Orders arrive, stock decreases, customers register, on the server you are about to stop using.
Every decision below follows from that.
Do not copy and then switch
The ordinary website migration: copy everything, point DNS, done, loses every order placed between the copy and the switch.
On a brochure site that gap costs nothing. On a shop it costs orders you cannot recover, from customers who were charged.
Two ways to close it. Maintenance mode during the cutover, so nothing new arrives. Or a final database sync immediately before switching DNS, which is invisible to customers and requires you to be watching.
For most shops maintenance mode is the honest choice: a short scheduled window beats an invisible one where someone's order vanished. Setting up a maintenance page deals with doing it with the right status code.
Lower the TTL days ahead
The length of the gap is decided by DNS, and the TTL has to be lowered before the change, not during it.
At 300 seconds the cutover is minutes. At the common default of four hours, you are choosing between a four-hour maintenance window and four hours of orders landing on two servers. Understanding DNS propagation has the detail.
Copy in the right order
Files first, database last. Files are large and slow and do not change much; the database is small, fast, and changes constantly.
Copying the database last means the smallest possible gap between the snapshot and the switch. Copying it first means every order during the file transfer is lost.
The addresses inside your data
Changing the site address setting changes what WooCommerce generates. It does not change addresses stored in your content, and a shop has more of those than a normal site: product images, page-builder layouts, email template settings, gateway callback URLs.
That needs a search and replace across the database, and it cannot be a plain SQL REPLACE, serialised data records its own string lengths, and a plain replace corrupts it. The symptom is settings reverting to defaults for no reason.
Use a tool that understands serialised data, then remove it. There is more on this properly in changing the WordPress site URL.
Payment gateways need attention separately
The part that fails after everything looks fine.
Gateways call back to your site to confirm payments. A webhook or IPN pointed at a specific URL. If that URL changed, or if the gateway's requests are blocked by a new firewall or a CDN, payments are taken and orders are never marked paid.
The customer is charged and sees nothing. That is the worst failure available in a shop migration, and it is silent.
Check each gateway's configured callback URL after the move, and place a real test order through each active method, not a test-mode order, a real one you refund afterwards. Configuring payment gateways goes into where those settings live.
Test on the new server before DNS moves
Map the domain to the new server in your hosts file. You see the migrated shop while customers still reach the old one.
Then walk the whole path: browse a category, view a variable product, add to cart, apply a coupon, reach checkout, and complete an order.
That last step matters most, because checkout touches more moving parts than anything else on the site: sessions, the database, the gateway, and mail.
Mail is part of a shop, not an extra
Order confirmations, password resets, stock alerts to you. A shop whose mail stopped is a shop taking orders nobody is told about.
Configure SMTP on the new server before launch rather than after, and send yourself a test order confirmation. Fixing WordPress email not sending goes into why mail from a new server is often accepted and then discarded.
Update SPF and DKIM to name the new sending server. That failure is gradual: mail keeps working for a fortnight and then increasingly lands in spam.
Turn off staging behaviour
If you rehearsed on a staging copy, check what came across with it.
Gateways left in test mode take no real money. Search engine discouragement leaves the shop invisible. Email sending disabled by a staging plugin means no confirmations.
All three look like a working shop and none of them are. The launch checklist sets out the general versions.
Keep the old server for a week
Not as a fallback for the shop: running both splits your orders across two databases, which is worse than any problem it solves.
Keep it so that late mail is not bounced, and so anything that landed there during the changeover can be retrieved. A week minimum, two if the shop is busy.
Reconcile the first day
Compare the order numbers on the new server against your gateway's own dashboard for the first day.
They should match. A payment in the gateway with no corresponding order is the callback failure described above, and finding it on day one means refunding two customers rather than fifty.
Also check stock levels against reality, since a database restored from a snapshot may be showing quantities from before the last orders. For the drift, see inventory and stock management.
The backup taken before a migration is the one that matters most, and a store's is harder than a site's. How to Back Up a Store That Takes Orders Continuously sets out the timing problem.
Coming from a different platform entirely is a different exercise, with passwords and addresses as the hard parts. How to Migrate from Another Platform to WooCommerce picks it up from there.