Copy your live site into a throwaway environment, run the update there, and click the five things that make the site money. That is the whole job, and it takes about ten minutes once you have done it twice.
The advice you usually get is "take a backup and use staging". Both are correct and neither tells you what to actually do inside the test environment, which is where the useful part is. This post is the routine.
We build SandyWP, a disposable WordPress sandbox, so we have an obvious interest here. The routine works on any staging setup you already have; the SandyWP-specific commands are marked as such.
Why a clean test install proves nothing
Most guides tell you to install the plugin on a fresh WordPress and see if it works. That test almost never fails, and it almost never matches what breaks in production.
Plugin updates rarely break in isolation. They break against your data, your other twenty plugins, and your PHP version.
The failures we see repeat in three shapes:
- A database migration that runs once on activation, against 40,000 posts instead of the developer's twelve, and times out halfway.
- A conflict with another plugin that hooks the same filter, which only exists on sites that run both.
- A dropped deprecation that is fine on PHP 8.1 and fatal on PHP 8.3, or the reverse.
None of those reproduce on a clean install. So the first rule is: test against a copy of the real site, with the real content and the real plugin list.
The routine
1. Know the rollback command before you touch anything
Write down the current version first. If you skip everything else in this post, do this one.
wp plugin list --update=available --fields=name,version,update_version
That gives you the slug and the version you are on. The rollback is the same command you use to update, with a version pinned:
wp plugin update woocommerce --version=9.4.2
The WP-CLI documentation describes --version plainly: "If set, the plugin will be updated to the specified version." It downgrades as happily as it upgrades.
There is also --dry-run, which "preview[s] which plugins would be updated" without doing it. Useful when you want to see the full blast radius of wp plugin update --all before you agree to it.
2. Copy the site, do not clone-and-hope
You want the database and wp-content as they are in production right now, not a copy from three months ago.
On SandyWP that is the free Cloner plugin: install it on the production site, connect the account, and it packages the database and wp-content into a new sandbox. Production is only read, never written back.
If you use your host's one-click staging, that works too. Just confirm it copied the database and not only the files, because a files-only copy will not reproduce a migration failure.
3. Match the PHP version to production, not to the default
This is the step people skip, and it quietly invalidates the whole test.
Check what production runs (wp cli info shows the PHP version), then set the test environment to the same. SandyWP sandboxes offer PHP 7.4, 8.1, 8.2 and 8.3 from a selector, and switching restarts the sandbox for a few seconds without touching files or the database.
If you are testing because you are also moving PHP versions, do the two changes separately. One variable at a time, or a failure tells you nothing about its cause.
4. Turn on debug logging before the update, not after
The update is the moment you most want the log, and after the fact you cannot get it back.
Set WP_DEBUG and WP_DEBUG_LOG on, and WP_DEBUG_DISPLAY off so nothing leaks into the page output. On SandyWP those are toggles on the site page, with the debug.log viewer sitting next to them.
Then empty the log, so everything in it afterwards belongs to the update.
5. Run the update
wp plugin update woocommerce
Or click Update in wp-admin. It makes no difference, except that WP-CLI shows you the version it went to and does not hide a fatal error behind a spinner.
If you have SSH into the sandbox, run it there and watch the log at the same time:
sandywp ssh my-site --cmd "wp plugin update woocommerce"
sandywp ssh my-site --cmd "tail -50 wp-content/debug.log"
6. Click the five things that pay the bills
Not "browse around and see if it looks fine". A specific list, the same list every time, written down once:
- Checkout, all the way to a completed test order. Not the cart page.
- The login and the paywall, as a logged-out visitor and as a subscriber.
- The form that emails you, and confirm the mail was actually generated.
- One post and one page on the front end, and the block editor on each.
- The admin screen the plugin owns, saving a setting and reloading it.
For sites with a membership gate or a booking flow, add those. The point is that the list exists before you start, so you are checking rather than wandering.
Then read debug.log. A clean-looking site with two hundred new deprecation notices is a plugin update that will become an emergency on your next PHP upgrade.
7. Snapshot first, so you can do it again
Before the update, save the copied site as a snapshot you can relaunch. On SandyWP a Template captures the sandbox's WordPress and PHP versions, plugins, files and database, and new sandboxes launch from it.
That matters because if something breaks you want to know whether it is the update or an interaction, and that means running it again from the same starting point. Launch a fresh sandbox from the snapshot, disable the suspect plugin, and rerun.
That second run is the one that produces a bug report a plugin author can act on, rather than "your update broke my site".
Throwing the environment away also matters more than it sounds. A staging server that survives becomes a stale staging server, and a stale staging server tests nothing. This is the argument on our upgrade testing page, and it is the reason the sandbox gets deleted at the end.
Should I update plugins one at a time?
Yes on production. No in the sandbox, if you are short on time.
In the sandbox, update everything, and if it holds, you have your answer in one pass. If it breaks, relaunch from the snapshot and bisect: half the plugins, then half again. Three or four rounds isolates it out of twenty.
On production, apply them one at a time even though the sandbox passed, because production has traffic and a sandbox does not. If something goes wrong you want a one-line rollback, not an investigation.
What about the WordPress fatal-error email?
Since WordPress 5.2, a fatal error during a page load triggers Recovery Mode: visitors get a "technical difficulties" screen, the admin email gets a secret link, and the offending plugin is paused for whoever uses that link. The Make WordPress Core announcement has the mechanism.
It is a good safety net and a bad plan. It only catches fatal errors on regular page loads, not the ones in cron or background tasks, and it does nothing about the far more common failure where nothing is fatal and the checkout button just stops submitting.
Treat it as the thing that saves you when the routine above did not, rather than as a substitute for it.
What a sandbox will not tell you
Being honest about this is the whole reason the routine is worth trusting.
A copy of your site on a different host will not reproduce load. If the plugin update makes a query 40x slower, ten page views will not show you that and ten thousand will.
It also will not reproduce your real payment gateway, your CDN and edge cache, email deliverability from your production domain, or a licensed pro plugin that checks the domain it is activated on. Some pro plugins will refuse to update at all on a copied domain, and you need to know that before you plan the test rather than during it.
Long-running cron behaviour is another one. If the plugin schedules a nightly job, a ten-minute sandbox tells you it scheduled it, not that it completes.
For those, staging on the same host as production, or a real canary deploy on your lowest-traffic site, is the right tool. Use it. Nothing here replaces watching the real thing after you ship.
The short version
Copy production. Match PHP. Turn on the log. Update. Click the five things. Read the log. Reset and bisect if it broke. Roll back with --version if it breaks in production anyway.
If you want that copy to take a couple of minutes and cost nothing to throw away, that is what SandyWP is for.
