Key Takeaways
- 70% of WooCommerce carts are abandoned — slow checkout is the #2 reason after unexpected costs
- Cart fragments (
wc-ajax=get_refreshed_fragments) is the single biggest checkout performance killer — it runs on EVERY page load, not just cart/checkout - Disabling cart fragments on non-cart pages saves 300–800ms per page load across your entire site
- Payment gateway scripts (Stripe, PayPal, Square) load 200–500KB of JavaScript — only load them on checkout
- A one-page checkout with minimal fields converts 20–30% better than multi-step with unnecessary fields
Checkout speed directly equals revenue
If your WooCommerce checkout takes more than 3 seconds to load, you’re losing money on every transaction. This isn’t speculation — Akamai’s ecommerce research shows that every 100ms of checkout delay reduces conversion rates by 1.5–2%. For a store processing £10,000/month, a half-second slowdown costs £750–1,000 in abandoned carts. This is part of our complete WooCommerce speed optimisation series, and checkout is where speed matters most.
The checkout page has a unique problem that makes it the hardest page to optimise in any WooCommerce store: it cannot be page-cached. Every visitor has a unique cart, unique session, unique address — the page must be generated fresh from PHP and MySQL on every load. That means server performance, database speed, and script efficiency all matter enormously.
Cart abandonment data tells a clear story. Baymard Institute’s 2025 research shows 70% of online shopping carts are abandoned. Slow checkout is the second most common reason (after unexpected shipping costs). 17% of shoppers abandon specifically because the checkout process was too slow or complicated. Checkout responsiveness is fundamentally an INP issue — every field interaction, every payment form keystroke, every button click needs to respond within 200ms or users perceive lag.
The cart fragments problem
Cart fragments are WooCommerce’s approach to keeping the mini-cart widget updated. When any page loads, WooCommerce sends an AJAX request to ?wc-ajax=get_refreshed_fragments that bootstraps the entire WordPress stack — loading all plugins, querying the database, generating cart HTML — just to return the current cart contents.
This happens on every single page of your site. Your blog posts, your About page, your Contact page — all make this AJAX call even though visitors on those pages almost certainly aren’t interacting with their cart. On a page-cached blog post that loads in 200ms, this AJAX call adds 400–800ms because it bypasses the page cache entirely and hits PHP.
The fix is straightforward — disable cart fragments on pages where the cart widget doesn’t need live updates:
// In your theme's functions.php or a site-specific plugin
add_action('wp_enqueue_scripts', function() {
// Only load cart fragments on WooCommerce pages
if (!is_woocommerce() && !is_cart() && !is_checkout()) {
wp_dequeue_script('wc-cart-fragments');
}
});
This single change saves 300–800ms on every non-shop page load. The trade-off is that the mini-cart widget won’t update in real time on non-shop pages — it’ll show the cart count from the initial page load. For most stores, this is perfectly acceptable.
For a more granular approach, you can replace the full fragment AJAX with a lightweight cart count endpoint that returns just the item count instead of the entire rendered cart HTML. We cover AJAX alternatives in depth in our WooCommerce AJAX optimisation guide.
Payment gateway script optimisation
Payment gateways are the second-biggest performance drain on WooCommerce stores — after cart fragments. Stripe’s JavaScript library weighs 150–250KB. PayPal’s SDK is 200–400KB. Square’s payment form adds another 200KB+. These scripts need to initialise, connect to external servers, and render payment forms — all of which blocks the main thread.

The critical realisation: these scripts only need to run on the checkout page. By default, most WooCommerce payment gateway plugins enqueue their JavaScript on every page. Loading Stripe’s library on your product pages serves zero purpose but costs 200–500ms of load time.
The fix depends on your gateway plugin. For Stripe:
add_action('wp_enqueue_scripts', function() {
if (!is_checkout()) {
wp_dequeue_script('stripe_v3');
wp_dequeue_script('wc-stripe-payment-request');
wp_dequeue_style('stripe_styles');
}
});
For PayPal:
add_action('wp_enqueue_scripts', function() {
if (!is_checkout()) {
wp_dequeue_script('ppcp-smart-button');
wp_dequeue_script('ppcp-oxxo');
}
});
Some gateways now support lazy loading — initialising their payment form only when the customer reaches the payment step. Stripe Elements, for example, can be initialised on demand rather than on page load, saving 100–200ms of main thread blocking time even on the checkout page.
Checkout field optimisation
Every field on your checkout form has a cost: render time, validation JavaScript, and cognitive load for the customer. The default WooCommerce checkout includes fields that many stores don’t need — company name, order notes, phone number (if you already have email for order updates).
Removing unnecessary fields speeds up both page rendering and form submission:
add_filter('woocommerce_checkout_fields', function($fields) {
unset($fields['billing']['billing_company']);
unset($fields['order']['order_comments']);
// Only remove phone if you don't need it for shipping
// unset($fields['billing']['billing_phone']);
return $fields;
});
Just as important: add proper autocomplete attributes so browsers can auto-fill addresses. This reduces interaction time from 45–60 seconds to 5–10 seconds for returning customers:
add_filter('woocommerce_checkout_fields', function($fields) {
$fields['billing']['billing_first_name']['autocomplete'] = 'given-name';
$fields['billing']['billing_last_name']['autocomplete'] = 'family-name';
$fields['billing']['billing_email']['autocomplete'] = 'email';
$fields['billing']['billing_address_1']['autocomplete'] = 'address-line1';
$fields['billing']['billing_city']['autocomplete'] = 'address-level2';
$fields['billing']['billing_postcode']['autocomplete'] = 'postal-code';
return $fields;
});
Address autocompletion services (Google Places, Loqate, Fetchify) add 50–100KB of JavaScript but save users significant time. The net conversion impact is usually positive for UK and US stores where postcode lookup is expected.
One-page vs multi-step checkout
A single-page checkout with all fields visible loads fewer resources, requires fewer page navigations, and converts better than multi-step approaches in most scenarios. Testing consistently shows that one-page checkouts with minimal required fields convert 20–30% better than multi-step flows.
That said, multi-step can work better for complex orders — stores with multiple shipping methods, B2B fields, or customisation options. The performance key is that each step must feel instant. If each step requires a full page load and server round-trip, multi-step checkout can easily take 8–12 seconds total. Using JavaScript-driven steps (where steps are shown/hidden client-side without page reloads) gives you the UX of multi-step with the performance of single-page.
Whichever approach you use, ensure the payment form initialises early. Stripe Elements and PayPal buttons need 500–1,500ms to initialise. If you wait until the customer clicks “Place Order” to load payment scripts, they’ll stare at a spinner. Pre-initialise payment forms as soon as the checkout page loads (or as soon as the payment step becomes visible in multi-step).
Server-side checkout optimisation
Because checkout pages can’t be page-cached, server-side performance is everything. Two visitors hitting checkout simultaneously need two PHP workers — if your hosting only has two workers, a third concurrent checkout visitor waits in a queue.
Redis session handling makes a measurable difference. WooCommerce stores session data (cart contents, applied coupons, chosen shipping method) in the database by default. Moving sessions to Redis reduces the database load on every checkout page load:
# In wp-config.php (if your host supports Redis sessions)
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
OPcache tuning is particularly important for checkout because every request runs the full PHP stack. Ensure OPcache is enabled with sufficient memory:
# php.ini optimisation for WooCommerce checkout
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.revalidate_freq=60
MySQL query caching helps checkout performance because many queries are repeated across sessions — product data, tax rates, shipping zone lookups. While MySQL’s built-in query cache was removed in MySQL 8.0, Redis or Memcached object caching achieves the same result at the application level.
Checkout-specific caching strategies
You can’t page-cache the checkout page, but you can cache components of it. Product data shown in the order summary, tax rate lookups, shipping rate calculations — these can all be cached at the object level.
WooCommerce’s shipping rate calculations are particularly expensive. Every checkout load recalculates shipping based on the customer’s address, cart weight, and shipping zone rules. Caching shipping calculations for 5–10 minutes reduces redundant API calls to shipping providers (Royal Mail, DPD, UPS) and database queries for zone matching.
Edge-side includes (ESI) offer an advanced approach for stores using Varnish or Cloudflare Workers. ESI lets you cache the static parts of the checkout page (header, footer, CSS) while dynamically rendering only the checkout form itself. This reduces TTFB by 50–70% compared to fully dynamic rendering, while still personalising the checkout for each visitor.
Browser caching for checkout assets (CSS, JavaScript, fonts) should be aggressive. These files don’t change between requests — cache them for 1 year with immutable headers. The checkout page itself should be Cache-Control: no-store to prevent stale cart data.
Testing checkout speed properly
Most speed testing tools don’t test checkout correctly. Lighthouse tests the page as an anonymous visitor — but your checkout page redirects anonymous visitors to the shop. Real checkout performance testing requires an authenticated session with items in the cart.
Use Chrome DevTools with a real checkout flow:
- Add products to cart normally
- Navigate to checkout
- Open DevTools → Performance tab → Start recording
- Fill out the form and interact with payment fields
- Stop recording and analyse the waterfall
Look specifically at: TTFB (server response time — should be under 400ms), payment gateway script initialisation time, form field interaction delay (this is your INP), and the total time from clicking “Place Order” to redirect. The checkout speed that affects your Core Web Vitals scores is measured on real user sessions, not synthetic tests.
For load testing concurrent checkout sessions, tools like k6 or Loader.io can simulate multiple customers checking out simultaneously. This reveals PHP worker bottlenecks that single-user tests miss entirely.
Why is WooCommerce checkout so slow?
WooCommerce checkout is slow because it can’t be page-cached — every request hits PHP and MySQL. Cart fragments AJAX adds 400–800ms, payment gateway scripts (Stripe, PayPal) load 200–500KB of JavaScript, and the database queries for cart contents, tax rates, and shipping calculations add another 200–500ms. Fix these three areas and checkout load time typically drops from 4–6 seconds to 1.5–2 seconds.
How do I disable WooCommerce cart fragments?
Add this to your theme’s functions.php: add_action('wp_enqueue_scripts', function(){ if(!is_woocommerce() && !is_cart() && !is_checkout()){ wp_dequeue_script('wc-cart-fragments'); }}); This dequeues the cart fragments script on all non-shop pages, saving 300–800ms per page load. The mini-cart widget won’t live-update on those pages, but it’ll still show the correct count on initial page load.
Should I use one-page or multi-step checkout?
One-page checkout with minimal fields converts 20–30% better in most cases because it requires fewer page loads and less total interaction time. Multi-step can work better for complex orders (B2B, custom products) but each step must use JavaScript-based show/hide rather than full page reloads. The worst option is multi-step with full page reloads — that multiplies server load and checkout time by the number of steps.
Does checkout speed affect WooCommerce conversions?
Yes, significantly. Research shows every 100ms of checkout delay reduces conversions by 1.5–2%. For a store with £10,000/month revenue, reducing checkout load time from 4 seconds to 2 seconds could increase conversions by 3–4%, adding £300–400/month in revenue. The fastest WooCommerce checkouts load in under 2 seconds and process payments in under 1 second.
How do I speed up Stripe on WooCommerce checkout?
Three fixes: First, only load Stripe scripts on the checkout page by dequeuing them on all other pages. Second, use Stripe Elements instead of Stripe Checkout for lower JavaScript overhead. Third, pre-initialise the Stripe Elements form on page load rather than waiting for user interaction — this shifts the 500–1,000ms initialisation time into the page load where it overlaps with other loading, rather than adding it to the payment interaction time.
Slow checkout costing you sales?
Get your free WooCommerce speed audit
We’ll identify exactly what’s slowing your checkout, how much revenue it’s costing you, and provide the specific fixes — with guaranteed results.