WooCommerce Checkout Slow? 12 Real Fixes That Cut Page Load by 60%+ (2026)

If your WooCommerce checkout takes 4+ seconds to respond — or worse, freezes on shipping or payment updates — the cause is almost always one of a dozen well-known problems. This is a diagnostic guide, not a "install a caching plugin" thread. Each fix tells you what to measure, what to change, and when it actually helps.

14-second narrated walkthrough: slow checkout → SimpleReview → PR with a fix

yourstore.com/checkout
SimpleReview extension
W SimpleReview Test Edit site 3 🔍 AI Review
Howdy, admin

Billing Details

Subtotal$ 128.00
Shipping$ 9.50
Stripe
PayPal
Apple Pay
Place Order
update_order_review
Load time4.8s
wp_options autoload2.1 MB
Checkout hooks34
PHP queries412
✓ Checkout optimized
Load time1.2s
wp_options autoload480 KB
Checkout hooks9
PHP queries78
Comment×
Checkout is 4.8s slow — fix hook|
Fix it ✓ Done
waiting for selection…
Profiling checkout
TTFB3.4s
AJAX tick1.4s
Root cause
hook: update_order_review
plugin: custom-tax-sync
remote call: 1.2s
Fix suggestion
Cache tax-sync in transient (5 min). Move hook → only on checkout submit.
✓ Auto-deployed
fix: cache tax-sync + move hook
−34 hooks → 76% faster TTFB
Click the SimpleReview icon → select the slow checkout → Fix it → auto-deploy
Installed a custom WooCommerce plugin or AI-generated snippet and your checkout got slow the next day? → SimpleReview reviews the repo and sends a PR with the exact hook to remove or cache.

Key Takeaways

  • WooCommerce checkout is slow on 90%+ of stores because of plugin hooks, not core WooCommerce.
  • Cart fragments (wc-cart-fragments.js) fire AJAX on every page — disable them everywhere except /cart/ and /checkout/.
  • Autoloaded options above 1 MB slow every request. Most stores ship 2–5 MB after a year of plugin churn.
  • The update_order_review AJAX re-runs all checkout hooks on every field change. Profile it with Query Monitor — if it takes over 1 second, one plugin is guilty.
  • PHP 8.1+ plus object caching (Redis) gives a 30–50% checkout speedup before any code changes.
  • Page caching does not help checkout — WooCommerce already excludes it — but the rest of the site should be cached so checkout is the only backend-heavy page.
  • Heartbeat API, Google Fonts inlined, and payment gateway JS (especially PayPal Smart Buttons) are the top three front-end offenders.

Fix 1: Profile First, Then Change Code

Before touching anything, install Query Monitor (free). Load /checkout/ and expand "Hooks & Actions" and "Queries". You are looking for three numbers: total queries, slowest query, and plugins attached to woocommerce_checkout_update_order_review, woocommerce_checkout_process, and woocommerce_after_calculate_totals.

Healthy checkout: under 80 queries, no query over 200 ms, under 10 hooks per checkout action. If you see 400+ queries or a single query above 1 second, you have a concrete target.

Fix 2: Kill Cart Fragments Sitewide (Except Cart/Checkout)

The single biggest front-end win. WooCommerce loads wc-cart-fragments.js on every page to refresh the mini-cart count via AJAX. On pages with no cart widget, it is pure waste — and it blocks admin-ajax.php.

// functions.php
add_action( 'wp_enqueue_scripts', function() {
    if ( is_cart() || is_checkout() ) return;
    wp_dequeue_script( 'wc-cart-fragments' );
}, 11 );

Real-world impact: 200–600 ms off every non-cart page, including category and product pages where users browse before checkout.

Fix 3: Shrink Autoloaded Options

Every WordPress request loads all rows from wp_options with autoload = 'yes'. Plugins dump session data, logs, and transients there and never clean up. Over a year this balloons.

Check your total:

SELECT SUM(LENGTH(option_value))/1024/1024 AS autoload_mb
FROM wp_options WHERE autoload = 'yes';

Anything over 1 MB is a problem. Above 3 MB and every request — including checkout — pays the tax. Find the biggest offenders:

SELECT option_name, LENGTH(option_value)/1024 AS kb
FROM wp_options WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC LIMIT 20;

Typical culprits: abandoned plugins, action_scheduler_ rows (switch to a cleanup cron), _transient_ that should not be autoloaded, session handlers from plugins that never clean up.

Fix 4: Object Caching (Redis or Memcached)

WooCommerce is query-heavy. Without object cache, every checkout AJAX call re-runs dozens of queries that did not change. With Redis, the second update_order_review tick drops from 1.5 s to 200 ms on most stores.

If you are on managed WooCommerce hosting (Kinsta, WP Engine, SpinupWP), object cache is usually one click. On a VPS, install Redis and the redis-cache plugin. Verify with Query Monitor: you should see most non-persistent queries disappear after the first load.

Fix 5: Audit Plugins Hooked Into Checkout

Every plugin that attaches to woocommerce_checkout_update_order_review runs on every field change. A single plugin making a remote API call there can turn a 400 ms checkout into a 3 s one.

Find them:

// functions.php — log what runs on update_order_review
add_action( 'woocommerce_checkout_update_order_review', function( $post_data ) {
    global $wp_filter;
    $hooks = $wp_filter['woocommerce_checkout_update_order_review'] ?? null;
    if ( $hooks ) {
        error_log( 'checkout hooks: ' . print_r( array_keys( (array) $hooks->callbacks ), true ) );
    }
}, 1 );

The worst offenders historically: tax-sync plugins (Avalara, TaxJar in aggressive mode), shipping quote plugins that hit carrier APIs on every address change, loyalty/points plugins that recalculate on every tick, currency converters that call remote FX APIs.

Fix 6: PHP 8.1+ and OPcache

If you are still on PHP 7.4, you are leaving 20–40% performance on the table. WooCommerce officially supports PHP 8.1+ as of WooCommerce 9.0. OPcache should be on with opcache.memory_consumption=256 and opcache.max_accelerated_files=10000.

Benchmark: Kinsta's 2024 PHP benchmark showed PHP 8.3 handling 2.9× more requests per second than PHP 7.4 on WooCommerce shop pages.

Fix 7: Disable or Throttle the Heartbeat API

The Heartbeat API polls admin-ajax.php every 15–60 seconds. On the checkout page, admin users sometimes have it firing at 15 s and stacking with update_order_review ticks. Throttle it or disable it on the front end:

add_action( 'init', function() {
    wp_deregister_script( 'heartbeat' );
}, 1 );

Keep it on the admin dashboard for post locking, but there is no reason for it on /checkout/.

Fix 8: Payment Gateway JS Bloat

PayPal Smart Buttons, Klarna, Afterpay, and Amazon Pay each load 100–300 KB of third-party JS, often synchronously. If you have all four enabled and the customer only ever uses Stripe, you are paying the full cost on every checkout.

Audit what the checkout actually loads in Chrome DevTools → Network → JS, sorted by Size. If a gateway JS loads but nobody uses it, disable the gateway or defer its script until the user selects it.

Fix 9: Remove Unused Checkout Fields

WooCommerce ships with 15 billing fields and 11 shipping fields. Every field you keep is work — validation, AJAX refresh, hook execution. If you sell a digital product and do not need shipping, disable shipping fields entirely. The woocommerce_checkout_fields filter lets you remove them:

add_filter( 'woocommerce_checkout_fields', function( $fields ) {
    unset( $fields['billing']['billing_company'] );
    unset( $fields['billing']['billing_address_2'] );
    unset( $fields['order']['order_comments'] );
    return $fields;
} );

Fix 10: Block Checkout Caching (Correctly)

WooCommerce already sets DONOTCACHEPAGE on /cart/, /checkout/, and /my-account/. Most caching plugins respect this. But a misconfigured caching plugin can still cache these pages, breaking nonces and session data, which appears to the user as "checkout hangs".

Verify: open the checkout in an incognito window, check response headers for X-Cache: HIT or Cloudflare's cf-cache-status. Should be MISS or DYNAMIC. If it is HIT, your cache is breaking checkout.

Fix 11: Defer Google Fonts and Third-Party Scripts

Most themes load 3–5 Google Font families with blocking <link> tags. Self-host them with font-display: swap or defer them. Move analytics, tag manager, chat widgets, A/B test libraries to async or load after checkout is interactive.

Rule: on /checkout/, nothing non-essential should block the main thread in the first 2 seconds.

Fix 12: Review Custom Code — Especially AI-Generated Snippets

The single most common cause of "checkout got slow last week" is a custom snippet. AI assistants are very good at generating working WooCommerce code and fairly bad at understanding which hooks run on every AJAX tick. A snippet that "just" calls an external API on woocommerce_checkout_process looks fine in isolation and kills performance in production.

If you shipped custom code recently — from ChatGPT, Claude, Cursor, Copilot, or a human — and the checkout degraded after, that is almost certainly the cause. Roll back the snippet, confirm the slowdown goes away, then decide whether to rewrite it correctly.

Shipped AI-generated WooCommerce code and checkout got slow?

SimpleReview reads your repo, runs the checkout under profiling, finds the exact hook or query causing the slowdown, and auto-deploys the fix. First fix is free.

Get a code review →

Which Fix Should You Start With?

SymptomMost likely causeFix to try first
Whole site is slow, not just checkoutAutoload bloat, no object cache, PHP 7.xFixes 3, 4, 6
Checkout slow, shop pages fastPlugin hooks on checkout actionsFixes 1, 5, 12
Address change freezes page for secondsupdate_order_review hooked by a tax/shipping pluginFix 5
First load fine, subsequent loads slowNo object cache, Heartbeat stackingFixes 4, 7
Checkout stalls with spinner foreverPage caching plugin caching /checkout/Fix 10
Got slow after adding a custom snippetCustom/AI-generated hook misuseFix 12 (roll back, then review)
Heavy on mobile, OK on desktopPayment gateway JS + Google FontsFixes 8, 11

Fast Diagnostic Checklist (15 minutes)

  1. Open /checkout/ in Chrome DevTools → Network. Note the total load time and the largest request.
  2. Install Query Monitor → check total queries and slowest query on checkout load.
  3. Run the autoload_mb SQL query. If over 1 MB, start there.
  4. Check PHP version (<?php phpinfo(); ?>). If under 8.1, upgrade before anything else.
  5. Add an address in the checkout, watch the update_order_review AJAX request in Network. If over 1 s, a plugin is the cause.
  6. Disable non-essential plugins one by one (or use Health Check plugin's troubleshooting mode) to isolate.
  7. If recent custom code — roll it back and retest.

FAQ

Why is my WooCommerce checkout so slow?
Most often: AJAX cart fragments firing on every page, autoloaded wp_options over 1 MB, and a plugin hooked into woocommerce_checkout_update_order_review making a slow remote call. Disable cart fragments sitewide except on cart/checkout, audit autoload, and profile with Query Monitor.
What is wc-ajax=update_order_review and why does it take seconds?
It refreshes the order totals every time a checkout field changes. It re-runs all checkout hooks, tax calculations, and shipping queries. Over one second means a plugin is hooked into it and is slow — usually tax, shipping quote, or loyalty plugins with remote API calls.
Should I disable WooCommerce cart fragments?
Yes, on every page except /cart/ and /checkout/. A one-line dequeue saves 200–600 ms on every other page.
Does a caching plugin fix a slow checkout?
No, because WooCommerce already excludes checkout from page caching. The fix that actually helps checkout is object caching (Redis), not page caching.
How fast should a WooCommerce checkout be?
Under 3 seconds time-to-interactive on a warm request. Update-order-review AJAX ticks should be under 500 ms. Above those, conversion drops measurably.
Can AI-generated snippets cause checkout slowdowns?
Yes, frequently. AI assistants often attach work to woocommerce_checkout_process or update_order_review without realizing those fire on every AJAX tick. If the slowdown started right after a new custom snippet, roll it back first.

Sources