The WordPress runtime environment as of August 2026

A homepage that opens normally on the new server does not mean the WordPress migration is finished. That state is usually closer to the first check that files and the database can also be read in the new environment. A safe migration finishes only after confirming that everything created up to the moment of the move is reflected, that real traffic reaches the new environment, that TLS, mail, cron, cache, and external integrations work there, and how far back and by what route a problem can be reversed. At the end, writes on the old environment are blocked and backups, credentials, DNS, firewall, and monitoring are all tidied up.

So a WordPress migration is safer managed in five stages — preflight, rehearsal, cutover, validation, decommission — than as a file copy plus a database import.

The latest WordPress release is 7.1. The 7.1 branch in the official release archive still lists only 7.1, so no maintenance release in the 7.1 line is visible at this point.[7]

The WordPress Hosting Handbook recommends PHP 8.4 or above for production. It states that PHP 8.5 is supported from WordPress 6.9 onward. PHP 8.2 and 8.3 sit in security support upstream while 8.4 and 8.5 are in active support.[2]

On databases, the baselines in different documents have to be kept apart. MySQL 8.0 or later in the WordPress requirements is a broad compatibility statement, yet MySQL 8.0's end-of-life date already passed in April 2026.[8] MariaDB 10.6 likewise carries an end-of-life date of 6 July 2026 in the Hosting Handbook. Pick an LTS line still in support for a new environment, and never read "WordPress core supports it" as meaning plugins and custom queries are automatically compatible too.[2]

WordPress core
Current official position: Latest release 7.1 / Baseline for a new migration target: Do not raise it during the migration merely because it is the latest
PHP public recommendation
Current official position: 8.3 or above / Baseline for a new migration target: A modern recommendation, not a floor
PHP operational recommendation
Current official position: Hosting Handbook recommends 8.4 or above / Baseline for a new migration target: Take 8.4 as the default candidate after verifying every plugin, theme, and custom code
PHP core minimum
Current official position: WordPress 7.1 requires PHP 7.4 or above / Baseline for a new migration target: A runnable floor, not a target version for a new environment
PHP 8.5
Current official position: Supported by WordPress core 7.1 and in active support upstream / Baseline for a new migration target: Choose it once all extension code and PHP extensions pass verification
Database public recommendation
Current official position: MariaDB 10.11 or later, or MySQL 8.0 or later / Baseline for a new migration target: Check the product's current support lifetime as well
Database legacy floor
Current official position: Runs on MySQL 5.5.5 or later / Baseline for a new migration target: End of life, so not for a new target
Current LTS candidates
Current official position: MySQL 8.4, MariaDB 10.11, 11.4, 11.8 / Baseline for a new migration target: Decide after testing plugins, custom queries, charset, collation, and SQL mode
HTTPS
Current official position: A baseline condition in WordPress requirements / Baseline for a new migration target: Verify redirects, proxy headers, and callback URLs, not only certificate issuance

Why core upgrades and infrastructure migration do not go together

Consider bundling a server and OS change, PHP 8.1 to 8.5, MySQL 8.0 to 8.4, WordPress 7.0 to 7.1, and simultaneous plugin and theme updates into one cutover. When an error appears, separating server configuration from PHP compatibility, from database behaviour, from a core change, from a plugin update is hard. The bigger problem is that once an update has altered database structure or stored data, reversing traffic to the old environment is not a safe rollback.

The WordPress 7.1 field guide likewise explains that changes to some bundled libraries affect the behaviour or styling of plugins that use them, so testing is required. The PHP compatibility table for WordPress core is a judgment about core's own scope and says nothing about the compatibility of installed plugins, themes, MU plugins, and custom code.[9]

The safe default order has three steps. Rehearse the new infrastructure against the existing WordPress, plugin, and theme versions. Complete the infrastructure migration and clear the observation window. Then perform the core, PHP, database, or plugin upgrade as a separate change.

Where the existing PHP or database is simply unavailable in the new environment and a change is unavoidable, record it not as a plain server move but as an infrastructure migration combined with a runtime upgrade. Split the acceptance criteria and rollback triggers per environment as well.

How the service works

Map dependencies and rehearse the transition — Group dependent systems, rehearse the move and agree rollback conditions before cutover.

Bulk copy, final sync, traffic cutover

The transition splits into three actions. The bulk copy makes the first copy of files, uploads, and database into the new environment. In that state the new environment is a rehearsal target, with external mail, payment, webhooks, and cron blocked or in test mode. Meanwhile the old environment keeps taking real changes.

Next comes the write freeze. Once writes from admin, forms, comments, the REST API, payment callbacks, cron, and queues are controlled, the final sync moves the last database state, the uploads delta, and any other mutable files. The new environment is now a cutover candidate, where the smoke test and data consistency checks happen.

Last is the traffic cutover. DNS, the reverse proxy, or the load balancer is changed so the new environment takes reads and writes, and the old environment stays write blocked with cron and queues disabled. Only after the observation window is cleared does the old environment get decommissioned.

If orders, registrations, comments, and uploads kept arriving on the old site after the bulk copy, the first copy is not the state as of cutover. Switching traffic without a final sync produces a site that loads but has lost its most recent data.

Master migration checklist

The five stages below are the body of this article. Preflight fixes what is being moved. Rehearsal performs the transition end to end once, and cutover moves current data and real traffic together. Validation approves on function and operational evidence rather than on a screen. Decommission treats shutting the old server down as migration work.

Each stage's table is a template filled with real values. Recording an owner and evidence per item is what stops the next person from making the same judgment again.

1. Preflight: fix what is being moved

Preflight is not just gathering server facts. It is the stage that decides what state is in scope for copying, what lives in external systems, and which environment is authoritative before and after cutover.

The environment compatibility matrix is a template to fill with real values. MATCH means a simple match, TEST_REQUIRED means a rehearsal is needed, and BLOCK means it must be resolved before cutover. Record the old and new values side by side and leave a verdict.

The WordPress Hosting Handbook describes json and mysqli as required PHP extensions. It recommends several more separately for remote requests, media, character handling, TLS, and compression. That is why matching PHP versions is not enough to call two server environments the same.[2]

Check each of the 23 Preflight Checklist entries below, retaining its completion mark and evidence.

After environment, plugins, themes, and custom code, verify write paths, uploads, caches, cron, and queues.

Verify mail, integrations, DNS, TLS, proxy, security rules, and restore capability; then finalize sources of truth and cutover approval. Each checklist item identifies its evidence record.

The source of truth is settled in one sentence. Write down which environment is authoritative at each moment, as below. Writing that only the WordPress database is authoritative is not enough. If uploads live on the filesystem, payment results at the external gateway, and mail status at the sending provider, the migration scope is already spread across several systems.

□ Preflight 1 / Scope document
Separate infrastructure changes, URL changes, and any Core/PHP/DB upgrades
□ Preflight 2 / Environment Matrix
Record WordPress, PHP, and DB versions and PHP extensions
□ Preflight 3 / Plugin Inventory
Record all active/inactive plugins, versions, required PHP, and custom tables
□ Preflight 4 / Theme Inventory
Record parent/child themes, custom templates, and build artifacts
□ Preflight 5 / MU Plugin·Drop-in inventory
Check mu-plugins, object-cache.php, advanced-cache.php, and other drop-ins
□ Preflight 6 / Custom Code Register
Check functions.php, snippets, standalone PHP, deployment scripts, and other custom code
□ Preflight 7 / Network Map
Check multisite status, site count, domain mapping, and subdomain/subdirectory structure
□ Preflight 8 / Writer Inventory
Classify write-heavy features including WooCommerce, booking, membership, comments, and forms
□ Preflight 9 / Uploads Inventory
Measure wp-content/uploads, separate upload paths, external storage, and recent changes
□ Preflight 10 / Cache Map
Check page-cache location and bypass routes
□ Preflight 11 / Object Cache Map
Check object-cache prefix, DB, drop-in, and sharing
□ Preflight 12 / CDN Configuration
Check CDN origin, cache rules, and purge paths
□ Preflight 13 / Cron Inventory
Check WP-Cron versus system cron and what runs on which server
□ Preflight 14 / Queue Snapshot
Check plugin queues, pending/failed jobs, and worker locations
□ Preflight 15 / Mail Flow Map
Record SMTP/mail API, sending domain, authentication, and bounce inspection
□ Preflight 16 / Integration Register
Check endpoints and secrets for forms, webhooks, payment callbacks, and external APIs
□ Preflight 17 / DNS Export
Check DNS records, current TTL, proxy status, and access holders
□ Preflight 18 / Certificate Inventory
Check every hostname’s TLS certificate and renewal owner
□ Preflight 19 / Proxy Contract
Check Host, Scheme, and Client IP headers forwarded by the reverse proxy
□ Preflight 20 / Security Rule Export
Check WAF and access-control rules affecting Admin, REST, and webhooks
□ Preflight 21 / Restore Evidence
Check that database, file, and configuration backups exist and can actually be restored
□ Preflight 22 / Source-of-Truth Table
Declare the source of truth for DB, uploads, and external transaction data
□ Preflight 23 / Cutover Runbook
Finalize acceptance criteria, rollback triggers, approvers, and contact routes
During rehearsal
The WordPress database and uploads are authoritative in the old environment. Cron and queues run only there, and payment and mail use the real external systems.
Write freeze and final sync
The database and uploads remain authoritative in the old environment but with writes stopped. Cron and queues are stopped or drained, and inbound callbacks are controlled separately.
Cutover candidate
The candidate authoritative copy of the database and uploads moves to the new environment. Cron and queues are still held back, and integrations accept test requests only.
After acceptance
The database and uploads become authoritative in the new environment. Cron and queues run only there, and consistency with the new endpoints is confirmed.
Observation window
Both authority and execution sit in the new environment, and reconciliation against external systems continues.
Layer
What must be compared
Pass evidence
WordPress coreVersion, auto-update policy, whether core was modifiedVersion, checksum, change record
PHPVersion, SAPI, FPM settings, memory and timeoutphpinfo or configuration export, functional test
PHP extensionsjson, mysqli, curl, mbstring, intl, openssl, xml, zip, image processing modulesExtension list plus upload and remote request tests
DatabaseMySQL or MariaDB and version, charset, collation, SQL mode, timezone, packet sizeImport log, key queries, character and sort validation
Web serverNginx or Apache, rewrite, upload limit, compression, static file handlingPermalink, admin, REST, and large upload tests
PluginsActive and inactive lists, versions, PHP and core requirements, licences, custom tablesAcceptance test per feature
ThemeParent and child theme, version, build artefacts, template overridesKey templates, responsive layout, admin screens
MU pluginsFile list, load order, per-environment conditionsBootstrap and admin function tests
Custom codeTheme functions, drop-ins, snippets, separate apps and APIsCode register and critical flow tests
MultisiteSubdomain or subdirectory, network tables, domain mapping, cookie and upload pathsNetwork admin and per-site tests
Uploads and storagePaths, ownership, permissions, external object storage, generated filesCounts, size, recent files, thumbnail validation
Object cacheRedis or Memcached, database index, prefix, serializer, drop-inRead, write, and session tests after a flush
Page cache and CDNCache key, bypass routes, purge, originHIT and MISS, admin exclusion, purge confirmation
WP-Cron and system cronInvocation method, interval, user, DISABLE_WP_CRONEvent list and execution log
QueueWorker location, pending and failed jobs, retriesQueue state and absence of duplicate execution
MailSMTP or API method, from domain, authentication, bounce and logActual delivery plus provider log
Webhooks and callbacksEndpoint, secret, IP restrictions, retry, idempotencyA unique test ID and the receipt log
DNS, TLS, proxy, WAFRecords, TTL, certificates, origin, forwarded headers, rulesTests from outside and against the origin
MonitoringUptime, PHP errors, web logs, database, disk, queue, alertsDashboard and alert routing verification
Environment compatibility matrix: MATCH is a simple match, TEST_REQUIRED needs a rehearsal, BLOCK must be resolved before cutover

2. Rehearsal: run the whole thing once before the real switch

Rehearsal is not a test that brings up a home page on the new server. It performs the copy, import, configuration, and validation in the same order as the cutover, and records how long each takes and where it fails.

If the production domain stays the same, using a hosts override or temporary proxy routing on an approved test machine reduces unnecessary database changes compared with rewriting every URL in the database to a temporary domain. If a temporary hostname is unavoidable, block real mail, payment, webhooks, and cron separately, not just search engine indexing.

Consider a URL change. WordPress options, widgets, theme settings, and plugin data can hold PHP serialized data. A serialized string stores the length of each value alongside it, so replacing a URL of different length with a global SQL REPLACE() corrupts the data. The official WordPress migration document warns about this and explains that WP-CLI's search-replace recognises and handles serialized data.[1]

The safe default is a dry run on a copy of the new environment first. Give wp search-replace the old and new addresses with --skip-columns=guid and --dry-run to see only what would change and how many rows. Remove --dry-run from the same command only after reviewing the result and the database backup. If a plugin uses custom tables not registered with WordPress, inspect the tables first and then decide about --all-tables-with-prefix. Targeting an entire multisite needs --network, but that flag alone does not complete the review of the network structure. WP-CLI's default behaviour targets tables registered to the current site, and --network and --all-tables-with-prefix widen that scope.[3]

Do not change guid even though it looks like a URL. WordPress uses it as a permanent identifier for a post and the official documentation states it stays the same when the domain changes. Changing guid makes feed readers treat existing posts as new ones.[1]

A successful dry run is not final evidence either. After the change, verify menus, block and widget settings, background images in CSS, media URLs, SEO metadata, plugin custom tables, and redirects on the real screens and in the database.

Isolate the staging or temporary host from production traffic
Pass criterion: No ordinary user reaches it, and search indexing and real external side effects are blocked
Run on the actual target PHP, database, and web server
Pass criterion: Critical flows work without fatal errors or a flood of deprecations
Restore file ownership and permissions
Pass criterion: WordPress writes only where required, with no excessive global write permission
Perform the database export and import
Pass criterion: No import errors, and key table and entity counts land in the expected range
Dry run and then apply the URL change
Pass criterion: Serialized data survives and guid values are unchanged
Configure permalinks and rewrites
Pass criterion: Posts, pages, REST API, and admin paths respond correctly
Upload creation and thumbnail generation
Pass criterion: Originals and derivatives are created and readable from public URLs
Run plugins, theme, MU plugins, and custom code
Pass criterion: Acceptance criteria pass per critical flow
Verify mail, webhooks, and payment in test mode
Pass criterion: No side effect reaches real users or real transactions
Time the bulk copy and the final sync
Pass criterion: Both fit inside the planned maintenance window
Rehearse the rollback
Pass criterion: Traffic reversal and reactivation of the old environment work as documented
Fix the rollback trigger
Pass criterion: Who stops it, on what evidence, and when is explicit

3. Cutover: move current data and real traffic together

The cutover runs in twelve steps. It starts from confirming the bulk copy, moves through the write freeze and cron and queue control, the final database and upload syncs, the final configuration, and the smoke test, then switches traffic. TLS and caches are checked before writes are opened on the new environment.

A write freeze does not end with an admin notice. WordPress write paths do not live only under /wp-admin/. Comments and registration, enquiry, booking and survey forms, the REST API, admin-ajax.php, payment, shipping and CRM callbacks, scheduled publishing and WP-Cron, plugin queues and retry workers, and application password and API requests from external programs are all write paths. Even with a maintenance notice on the admin screens, webhooks and cron that keep running change the data again after the final database sync. On write-heavy sites, stop every writer, or record the writes that cannot be stopped in a separate ledger and reconcile them.

For a site that cannot tolerate even a short write freeze, the plain final dump in this runbook is not enough. It calls for a separate online migration design with replication or change data capture, callback reprocessing, and consistency reconciliation.

A DNS TTL does not fix the completion time. Lowering the TTL in advance makes resolvers fetch the new record sooner once their existing cache expires. But a TTL already fetched keeps counting down, and some resolvers serve expired data temporarily to survive an outage. So never promise a cutover time on the basis that "the TTL is 300 seconds, so the whole world sees the new server in five minutes".[6][10] After the switch, check results from several resolvers and networks, and identify which backend served a request from server logs or a deployment marker made for the test. Never put sensitive information such as an origin IP or an internal hostname into that marker.

Seven things get checked on TLS, proxy, and WAF. Whether every real hostname is in the certificate. Whether TLS between edge and origin is also correct. Whether the HTTP to HTTPS redirect creates a loop. Whether the reverse proxy passes the original host and the HTTPS scheme to WordPress correctly. Whether the new origin IP, port, and health check are in place. Whether the WAF wrongly blocks login, admin, the REST API, webhooks, or payment callbacks. And whether a write can still be created by connecting directly to the old origin.

Step
Action
Completion condition
1Confirm the bulk copy is completeThe database and files as of the baseline exist in the new environment
2Announce the change and start the write freezeWrite paths for admins, users, APIs, and callbacks are controlled
3Control cron and queues in the old environmentNo new data or external side effect arises during the final sync
4Final database syncThe database up to the freeze point is reflected in the new environment
5Final upload syncFiles added, changed, or deleted since the bulk copy are reflected
6Apply final URL and environment configurationProduction URL, database, secrets, and proxy settings match the target
7Cutover candidate smoke testNo blocker on login, read, write, or upload
8Switch DNS, proxy, or load balancerExternal requests arrive at the new environment
9Verify TLSCertificate, chain, redirects, and forwarded scheme are correct
10Invalidate page cache, object cache, and CDNOld responses, old origin, and stale objects are gone
11Open writes on the new environmentOnly the new environment writes as the authoritative copy
12Keep the write block on the old environmentNo new data is created through a bypass route
Cutover order: twelve steps and the completion condition for each

4. Validation: approve on function and operational evidence, not on a screen

Validation does not end with "someone looked around and it seemed fine". Fix owners and pass criteria per item in advance. Then leave re-checkable evidence such as request IDs, logs, and delivery results.

WP-Cron and system cron are different things. WP-Cron is not a scheduler that runs continuously like a traditional system cron. By default it checks for due tasks when a page load occurs. With no traffic, work runs later than its scheduled time.[11] Sites configured to call wp-cron.php or WP-CLI on a system cron often disable the page-load path with DISABLE_WP_CRON. When migrating, confirm two things separately: that the scheduled events still exist inside WordPress, and that the new server's OS scheduler actually calls WordPress cron. The wp cron test command inspects WP-Cron spawn behaviour. In a system cron setup, also check the OS scheduler's execution log and the completion record of actual events. If the old and new servers both run cron, mail, subscriptions, bookings, and inventory sync get processed twice.[4]

Mail function success and mail delivery are different. wp_mail() returning true does not mean the recipient received anything. The official function documentation states the value only means the transport used handled the request without error.[5] Mail validation needs six pieces of evidence. Whether WordPress or a plugin created the send request. Whether the SMTP or mail API provider accepted it. Whether the sending domain and its authentication are correct. Whether it arrived in a real test mailbox. What the spam, bounce, and block status is. And whether each template — password reset, order, form — was checked. Never pass on a PHP mail() call or a wp_mail() return value alone.

An all-green Site Health is still not full acceptance. Site Health is useful for checking configuration facts and known problems across WordPress, plugins, theme, server, database, and filesystem permissions. It also catches disabled uploads, loopback failures, outdated PHP, and blocked HTTP requests.[12] It does not, however, validate order payment, real mail delivery, external webhooks, analytics, current-data consistency, DNS switchover, or rollback capability. So an all-green Site Health is one item of migration acceptance, not the whole evidence.

Subject
Default owner
Pass criterion
HomeWordPress ownerThe expected home page opens on the production domain and is served by the new backend
ReadContent ownerRepresentative posts, pages, search, taxonomy, and media work and recent content is present
AdminWordPress ownerDashboard, menus, editor, and plugin screens show no errors or redirect loops
LoginApp ownerLogin, logout, password reset, and role-based access all work
SessionApp ownerSessions persist across requests and are not wrongly shared with the old environment
WriteContent ownerA test post and a settings change save to the new database and appear on the front end
UploadContent ownerFile upload, thumbnail generation, retrieval, and deletion all work
FormBusiness ownerSubmitted data is stored and the downstream processing state is confirmed
EmailMail ownerNot only request handling but actual receipt, provider log, and bounce status
WebhookIntegration ownerA unique test ID passes signature verification and is processed exactly once
PaymentCommerce ownerIn an approved test or sandbox flow, callback and order state agree
WP-CronWordPress ownerScheduled events run through the intended invocation and do not run twice
System cronInfrastructure ownerRuns as the intended user, interval, and command, and calls only the new environment
QueueApp ownerPending and failed counts are in range and old and new workers do not run together
Object cacheApp ownerRegenerates correctly after a flush and its keys do not collide with another environment
Page cacheWeb ownerDynamic routes bypass the cache and HIT and MISS on public pages match intent
CDNWeb ownerUses the new origin and no old content survives a purge
RedirectsSEO and web ownerHTTP, WWW, and legacy URLs land correctly with no chains or loops
Canonical URLSEO ownerOnly the public URL is emitted as canonical and no temporary host remains
robotsSEO ownerMatches the production policy with no leftover staging-wide block
SitemapSEO ownerUses production URLs, includes key content, and responds correctly
AnalyticsAnalytics ownerPage views and key events are collected and tags do not fire twice
LogsOperations ownerPHP fatals, database errors, permission errors, and 5xx do not rise abnormally
MonitoringOperations ownerUptime, latency, error, disk, database, and queue monitoring target the new environment
Site HealthWordPress ownerNo migration-related critical issue, and environment information matches the matrix
Business acceptanceBusiness approverEvery core business journey passes and unresolved risk sits inside the approved range
Validation, owner, pass criteria: the twenty-six acceptance items
How the service works

Operations connected from observation to improvement — Respond using service indicators and alerts, then connect change records and incident reviews to improvements.

5. Decommission: turning off the old server is migration work too

Do not delete the old server the moment the new one looks healthy. Leaving the old environment alive indefinitely is not safe either. Stale servers, plugins, credentials, and firewall rules linger unmanaged and create new attack surface and operational confusion.

The length of the observation window cannot be identical for every site. It has to be long enough to actually observe one cycle of the critical scheduled jobs, a real or approved synthetic write flow, mail, webhooks and payment callbacks, cache expiry and regeneration, real traffic during business hours, and the scheduled runs of backup and monitoring. Where a critical job runs once a month, two days of a healthy homepage is not grounds for calling that job validated.

Run the observation window
Closing condition: No unresolved critical issue and the exit criteria are met
Write block on the old environment
Closing condition: No new data can be created through a bypass domain, IP, or admin route
Stop old cron and queues
Closing condition: No external side effects and no duplicated work
Final backup of the old environment
Closing condition: A restorable copy of database, files, and configuration, with its identifier kept
Fix backup retention
Closing condition: A deletion date and owner consistent with legal, contractual, and operating policy
Credential rotation
Closing condition: Database, SMTP, API, and webhook secrets held by the old server are rotated as needed
DNS cleanup
Closing condition: Old records, temporary hosts, and verification entries removed
TLS cleanup
Closing condition: Unused certificates, challenges, and renewal jobs cleared
Firewall and allowlist cleanup
Closing condition: Old IPs, ports, and admin access grants removed
Monitoring cleanup
Closing condition: Duplicate alerts removed and required historical data retained
Backup and security agent cleanup
Closing condition: Unnecessary cost, permissions, and duplicate jobs removed
Shutdown approval
Closing condition: Approval recorded from business, application, and infrastructure owners
Server termination
Closing condition: Termination time, asset ID, and final evidence recorded
Post-migration document update
Closing condition: Runbook, architecture, credential owners, and asset registry brought current

WordPress-specific rollback contract

A rollback contract is not the sentence "if something goes wrong we put DNS back". In WordPress, the database, uploads, cron, queues, forms, orders, mail, and callbacks all change state at once, so the first thing to settle is how late a simple return is still possible.

If the new environment has not yet taken real writes, reversing traffic to the old environment and lifting the write block is generally available. That stage is the simplest rollback window.

Once writes have started in the new environment, orders and payment states, registrations, logins and password changes, comments, posts and bookings, uploaded files, form submissions, webhook processing results, changes made by cron and queues, and mail already sent all exist there. Reversing traffic alone at that point makes data created in the new environment disappear from users' view, or gets the same callback and queue processed twice.

So one of four things is needed: safely replay the new writes into the old environment; reconcile both databases against the external ledger by hand; forward fix in the new environment instead of returning to the old one; or lock new writes again and run in a restricted mode until the risk clears. Which of these is possible has to be decided before cutover. Raising it at rollback time means the data has already diverged.

The general rollback architecture spanning code, configuration, database, and traffic is covered in a separate document. This article concentrates on the execution contract that applies those principles to WordPress databases, uploads, cron, plugins, and external callbacks.

Field
What it records
Rollback authorityThe role that approves a return, and its deputy
Decision deadlineThe last moment after cutover at which a simple return is still a judgment call
Old environment modeWrite blocked, cron and queues disabled
Source of truth before freezeThe old database and uploads
Source of truth after acceptanceThe new database and uploads
Traffic reversal methodExecution order for DNS, proxy, and load balancer
Restore pointBackup identifiers immediately before and after the final sync
Rollback triggerConcrete conditions on login, write, payment, data integrity, and errors
New-write detectionThe posts, users, orders, uploads, forms, and queue items created in the new environment
External reconciliationHow payment, webhook, mail, and CRM state is reconciled
Cache actionThe order of object, page, and CDN cache invalidation
Cron and queue authorityWhich environment is reactivated, and when
Evidence ownerWho collects logs, database comparisons, and request IDs
Business approvalThe role that approves the risk of data loss and duplicate processing
Closure criteriaThe conditions that declare the rollback complete and operations normal
Rollback contract template: the fifteen fields filled before cutover

Additional items by site type

Each site type adds items on top of the base checklist. Six strands are set out below.

The official WordPress migration document likewise explains that multisite is more complex than a single site because server names and paths exist in several places in the database. wp_site, wp_blogs, per-site options, and settings such as SUBDOMAIN_INSTALL have to be reviewed separately.[1]

General content site
What to add: Confirm whether comments, registration, and forms really create writes; scheduled publishing and sitemap refresh; recent uploads delta
Write-heavy site
What to add: The full set of APIs under write freeze, the order, booking, inventory, and subscription ledgers, payment callback retry and idempotency, queue drain, final entity counts, and tracking of new writes after cutover
WooCommerce
What to add: Validate orders, payments, refunds, inventory, coupons, mail, webhooks, and scheduled actions separately, and reconcile state against the external payment gateway ledger
Membership and LMS
What to add: Login sessions, roles, enrolment state, progress, subscription renewal, password mail, and background jobs
Multisite
What to add: wp_site, wp_blogs, per-site options, domain mapping, network-activated plugins, upload paths, wildcard DNS and TLS, cookie domain, and network admin
Multisite URL change
What to add: Confirm the WP-CLI --network scope, review each site's home and siteurl and upload settings and the network tables by hand, and confirm whether the subdomain or subdirectory mode changes

Observation log template

Do not copy credentials, personal data, or full payment details into the observation log. Where necessary, keep only a minimal identifiable request ID or internal evidence ID. Record one observation per row and fill in the timestamp, observer, test ID, observed value, result, and the action and its owner alongside it.

When closing the observation window, record at least the start and end times, the core journeys and scheduled jobs observed, mail delivery confirmation, webhook and payment reconciliation results, whether any write was detected on the old environment, open incidents, whether rollback artefacts were verified, and who approved the shutdown.

Cutover
Function or event: Login / Backend serving it: New / Expected: Login succeeds and the session persists / Evidence: Log ID
Validation
Function or event: Upload / Backend serving it: New / Expected: Original and thumbnail are generated / Evidence: Screenshot or log
Validation
Function or event: Mail / Backend serving it: New / Expected: Actual receipt / Evidence: Provider message ID
Observation
Function or event: Cron and queue / Backend serving it: New / Expected: Runs on schedule, exactly once / Evidence: Event or job ID
Observation
Function or event: Error review / Backend serving it: New / Expected: No abnormal rise against the baseline / Evidence: Dashboard

What counts as a finished migration

"The site looks fine on the new server" is closer to the first row of validation. To say a migration finished safely, six questions all need an answer. Where does the final data live? Did writes ever occur in the old and new environments at the same time? Did the real functions used by users, admins, and external systems pass? Do mail, cron, queues, cache, and webhooks run only in the new environment? If something fails, how far back and by what route can it be reversed? And when, on whose approval, do the old server and its credentials go away?

Start by copying this article's master migration checklist into a real runbook and filling in owners and evidence. General rollback design and backup restorability are each covered in separate documents, and the division of WordPress operating responsibility after the move is managed in its own operations document.