A WooCommerce checkout is slow for one of four reasons: the server takes too long to build a page that can never be cached, payment and tracking scripts weigh the page down, shipping and tax lookups call outside services every time the address changes, or placing the order waits for payment, stock, emails and extensions one after another. The fix depends on which of the three moments is slow: opening the checkout, updating the totals, or clicking Place order. This guide shows how to time each moment in ten minutes and what to change for each cause. It is part of the WooCommerce store checklist, where the checkout is step 5.
Quick answer
- Time three moments: the checkout page loading, the totals updating after you change the address, and Place order until the thank-you page.
- Slow page load: measure Time to First Byte on the checkout. Over about 800 ms means the host, PHP version or missing object cache.
- Slow totals update: live shipping rates, tax services and address plugins that call outside APIs on every change.
- Slow Place order: the payment gateway's API, emails sent during the request, and extensions that sync stock or orders to other systems.
- Heavy page: disable payment methods and express buttons you do not use, and keep chat, heatmaps and A/B tests off the checkout.
- Never cache the checkout to make it faster; it breaks orders.
How the checkout works, and where the time goes
Knowing what happens at each moment tells you where to look.
1. Opening the checkout. The page is built by PHP on every request, because it is different for every shopper. The server loads WordPress, WooCommerce and every active plugin, reads the cart from the session, calculates totals and shipping, and renders the form. The browser then loads the theme, WooCommerce's scripts and each payment method's scripts.
2. Updating the totals. When the shopper types an address or changes the country, WooCommerce recalculates shipping, tax and totals. The classic checkout (the [woocommerce_checkout] shortcode) sends a ?wc-ajax=update_order_review request. The Checkout block, the default for new stores since WooCommerce 8.3, calls the Store API, for example /wp-json/wc/store/v1/cart/update-customer or a /batch request. Each call runs PHP again, plus any outside lookups for shipping rates or tax.
3. Placing the order. Clicking Place order sends the form to ?wc-ajax=checkout (classic) or /wp-json/wc/store/v1/checkout (block). WooCommerce validates the form, creates the order, reduces stock, calls the payment gateway's API, sends the order emails and runs every extension hooked into the order, before the shopper sees the thank-you page.
How to time a slow checkout
You need a browser and ten minutes. Test as a shopper would: logged out, in a private window.
- Add a product to the basket and open the checkout.
- Open the developer tools (F12) → Network, tick "Disable cache", and reload. Click the first request (the checkout page itself) and open Timing: Waiting for server response is its Time to First Byte.
- Filter by "Fetch/XHR". Change the country or postcode and watch the
update_order_reviewor Store API request appear. Its duration is the totals update. - Use your gateway's test mode and a test card, click Place order and time the
checkoutrequest until the thank-you page loads. - Sort the Network list by domain. Count the scripts from payment providers, tracking and other services.
For the server side, the free Query Monitor plugin shows, for each page and AJAX request, the slowest database queries, the plugins that made them, and the outgoing HTTP API calls with their duration. Those outgoing calls are often the answer: a carrier rate lookup of 2 seconds shows up there by name. Use it on staging, or on production for a short while, logged in as an administrator.
| What is slow | Usual cause | Where to look |
|---|---|---|
| The page before anything shows | Server: hosting, PHP, no object cache | TTFB of the checkout request |
| The page after the HTML arrives | Gateway and third-party scripts | Network tab, sorted by domain |
| Totals after an address change | Shipping, tax or address APIs | Duration of the update request; Query Monitor's HTTP API calls |
| Place order | Gateway API, emails, order-sync extensions | Duration of the checkout request; Query Monitor |
Cause 1: a slow server on an uncached page
Product and category pages can come from a page cache; the checkout never can. So the checkout shows your server's real speed. Google's web.dev guidance rates a Time to First Byte of 800 ms or less as good. A checkout that needs 1.5 to 3 seconds before anything happens has a server problem, not a theme problem.
What to change, in order of cost:
- PHP version. Run a version WordPress and WooCommerce currently support; WooCommerce recommends 8.3 or newer.
- Persistent object cache. Redis or Memcached, if the host offers it, keeps options, sessions and product data in memory between requests.
- Plugins that load on every request. Every active plugin runs on the checkout. Remove the ones you do not use; the report's plugin cost list shows the heavy ones on the front end.
- The hosting plan. If the plan is the limit, WooCommerce hosting shows how to compare hosts by uncached TTFB on your own store.
With an empty basket, the classic checkout redirects to the cart, so a TTFB test on /checkout/ usually measures the cart. That is still an uncached WooCommerce page and a fair proxy. For the exact number, use the Network tab with a product in the basket.
Cause 2: payment gateway and third-party scripts
Each payment method loads its own scripts: a card-field library, a wallet SDK for Apple Pay, Google Pay or PayPal buttons, sometimes a fraud-detection script. Three gateways with express buttons can add more JavaScript than the rest of the page combined, and some load it on every page of the store, not only the checkout.
- Disable payment methods you do not use under WooCommerce → Settings → Payments. A method that is installed and enabled loads its scripts even if nobody picks it.
- Limit express buttons (Apple Pay, Google Pay, PayPal) to the places they earn their keep. Most gateways let you choose between product page, cart and checkout.
- Check where gateway scripts load. Open a blog post and look for the gateway's domain in the Network tab. If it loads there, look for a setting to restrict it, or ask the gateway's support.
- Keep the checkout clean. No chat widget, heatmap, A/B test or social pixel is worth a slower payment step; this also narrows the room for card-skimming scripts, as WooCommerce security explains.
Cause 3: shipping, tax and address lookups
Totals that take seconds to update after the shopper types a postcode almost always come from an outside call.
- Live carrier rates. Plugins that fetch rates from a carrier's API make a request each time the address or basket changes. WooCommerce keeps calculated rates in the session and only recalculates when the package changes, but a slow carrier API still adds its full response time. Use flat or table rates where you can, and set a short timeout in the plugin if it has one.
- Many shipping methods and zones. Every method in the matching zone is calculated. Remove methods and zones you no longer offer.
- Tax services. Automated tax plugins call their service to calculate tax for the address. Check their timeout and caching options.
- Address autocomplete and validation. They call an outside API as the shopper types. Keep one, not two.
- "Hide shipping costs until an address is entered", under WooCommerce → Settings → Shipping → Shipping options, skips rate calculation before there is an address to calculate for.
In Query Monitor, the HTTP API calls panel on the update request shows each outside call and how long it took. The slowest one is your answer.
Cause 4: slow Place order
The moment after Place order is the most stressful for a shopper, and it does the most work.
- The gateway API. Authorising the payment takes a round trip to the provider. It is usually well under a second; if it is not, check the gateway's status page and your server's connection to it.
- Order emails. By default, WooCommerce sends the new-order and confirmation emails while the shopper waits. Sending through a slow SMTP server can add seconds. Use a transactional email service with an API, or turn on "Deferred emails" under WooCommerce → Settings → Advanced → Features (WooCommerce 10.8 and later), which sends them in the background through the Action Scheduler.
- Extensions that act on new orders. Stock sync with a marketplace or warehouse, accounting exports, CRM and marketing tools often run on the order hook and call their own APIs. Look for a setting to run them in the background, or replace them with ones that do. WooCommerce's own webhooks are already delivered in the background by default.
- Fraud checks that call a scoring service during checkout. Keep one, and prefer the gateway's own.
If Place order is slow only sometimes, background jobs may be piling up. Speeding up the WooCommerce backend covers the Action Scheduler queue and a real server cron.
Cause 5: requests competing with the checkout
Other requests on the checkout page compete with it for the same PHP workers:
- Cart fragments, the request that refreshes the header basket, should run on the cart and checkout only if the theme needs it. On other pages it wastes a PHP worker on every view. WooCommerce cart fragments shows how to stop it.
- admin-ajax requests from plugins (live chat, popups, counters) and the WordPress Heartbeat, which runs every minute or so on pages where a plugin enables it.
On a small plan with few PHP workers, three of these at once make the checkout's own request wait in a queue.
Do not cache the checkout to make it faster
A cached checkout is fast and broken: it serves one shopper's basket and security token to the next, and orders fail with "session expired" errors. The WooCommerce checker fetches /cart/ and /checkout/ as an anonymous visitor and reads the cache headers to catch exactly this.
Keeping cart, checkout and account pages out of the cache shows the exclusion for each cache layer.
Classic checkout or Checkout block?
Neither is always faster. The Checkout block loads a larger JavaScript bundle up front but updates totals through the Store API without reloading the order review. The classic checkout loads less JavaScript but re-renders the review table with each update_order_review call. Extensions matter more than the choice: a gateway or shipping plugin that does not fully support the block may fall back to slower behaviour. If you are thinking of switching, test both on a staging copy with your real gateways and shipping, using the timing steps above.
Common mistakes
- Measuring the home page. It comes from the cache. The checkout is the page that shows the server's real speed.
- Testing while logged in as an administrator. Admin toolbars and plugins that load only for admins change the numbers. Use a private window.
- Enabling every payment method "just in case". Each one loads scripts and adds choices. Keep the ones your customers use.
- A cache rule that includes the checkout. It turns a slow checkout into a failing one.
- Blaming WooCommerce core. Profiling almost always finds an outside API call, a heavy extension or a small hosting plan.
Questions people ask
Why does my WooCommerce checkout take so long to load?
Because the checkout can never come from a page cache, so every visit runs WordPress, WooCommerce and all active plugins on your server. A slow host, an old PHP version or no object cache shows up there first. Measure its Time to First Byte in the browser's Network tab; over about 800 ms points to the server. Then check how many payment and tracking scripts the page loads.
Why is the WooCommerce "Place order" button slow?
Placing an order creates the order, reduces stock, calls the payment gateway's API, sends order emails and runs every extension hooked to new orders, all before the thank-you page appears. Slow SMTP email and extensions that sync orders to other systems are the usual culprits. Send email through a transactional email API or turn on deferred emails, and move syncing extensions to the background.
Why do WooCommerce checkout totals take so long to update?
Each change of address or country recalculates shipping, tax and totals on the server. Live carrier rates, tax services and address validation plugins call outside APIs during that request, and a slow API delays every update. Query Monitor's HTTP API calls panel shows which call is slow. Use flat or table rates where possible, and remove shipping methods and zones you no longer offer.
Is the WooCommerce Checkout block faster than the classic checkout?
Not automatically. The Checkout block loads more JavaScript up front but updates totals through the Store API; the classic shortcode checkout loads less but reloads the order review on each change. Your gateways, shipping plugins and hosting usually matter more than the choice. Test both on a staging copy with your real extensions before switching.
Can I cache the WooCommerce checkout page?
No. The checkout holds the shopper's basket, address and a security token that is valid only for their session. A cached checkout shows one shopper's details to the next and makes orders fail with "session expired" errors. Exclude the checkout, cart and my-account pages from every cache layer, including the CDN, and make the server fast instead.