WordPress Performance FAQ
My WooCommerce checkout is not cached for obvious reasons, because it contains cart, customer, payment, shipping, tax, and session data. But it still seems to load every active WordPress plugin on the site, including plugins that have nothing to do with checkout.
Is that part of the performance problem?
In other words, even if checkout must remain dynamic and cannot be served from page cache, does it still make sense to ask whether unrelated plugins, hooks, services, and PHP code should participate in the checkout request at all?
Yes. In many WooCommerce stores, that is a significant part of the performance problem.
People often frame checkout performance as:
"Checkout can't be cached, therefore it will always be slow."
But that's only half the story.
A checkout request is dynamic, which means PHP, WordPress, WooCommerce, sessions, cart calculations, shipping calculations, taxes, payment gateways, and customer-specific data must execute. However, that does not automatically mean every plugin on the site should be loaded or every hook should run.
What actually happens on a WooCommerce checkout request
A typical checkout request goes roughly like this:
- Web server receives request.
- WordPress boots.
- Active plugins are loaded.
- Theme loads.
- WordPress and WooCommerce hooks fire.
- WooCommerce calculates cart totals, shipping, taxes, discounts, etc.
- Payment gateway code initializes.
- Checkout page is rendered or an AJAX endpoint responds.
The important observation is that WordPress loads active plugins before it even knows much about what page you're ultimately rendering.
So if you have:
- SEO plugins
- analytics plugins
- form plugins
- page-builder plugins
- social sharing plugins
- backup plugins
- marketing automation plugins
- search plugins
- custom code snippets
they often participate in the request lifecycle whether they are useful for checkout or not.
Why unrelated plugins can still hurt checkout
The cost isn't just plugin count. It's what they do during initialization.
Examples:
Cheap plugin
add_action('init', function() {
// register a custom post type
});
Cost is minimal.
Expensive plugin
add_action('init', function() {
$remote_data = get_option('some_large_option');
expensive_processing();
});
Now every checkout request pays for that work.
Really expensive plugin
add_action('woocommerce_before_checkout_form', function() {
external_api_call();
});
Now checkout performance directly depends on an external service.
WooCommerce checkout is especially sensitive
Checkout often triggers:
- cart recalculations
- shipping rate lookups
- tax calculations
- coupon validation
- payment gateway initialization
- customer session reads/writes
- multiple AJAX requests
Because the baseline work is already substantial, every additional plugin overhead becomes more noticeable.
A homepage might be served from cache in 10 ms.
A checkout request might require 500–1500 ms of backend processing.
Adding 100 ms of unnecessary plugin work to checkout is far more visible than adding 100 ms to a cached page.
A useful mental model
Think of checkout performance as:
Checkout Time
=
WordPress Bootstrap
+ Plugin Initialization
+ Theme Initialization
+ WooCommerce Logic
+ Database Queries
+ External API Calls
+ Rendering
Most store owners focus only on:
WooCommerce Logic
But on many sites:
Plugin Initialization
is surprisingly large.
Should unrelated plugins participate?
This is exactly the right question to ask.
Not:
Can checkout be cached?
but:
What code actually needs to execute for checkout?
Ideally, only things directly related to:
- WooCommerce core
- cart/session handling
- shipping
- taxes
- payment gateways
- fraud detection
- checkout-specific functionality
should materially affect the request.
If an SEO plugin, popup plugin, page-builder extension, analytics suite, or marketing plugin is consuming measurable time during checkout, it's reasonable to investigate whether it can be disabled there, deferred, or optimized.
How to verify
The best approach is profiling rather than guessing.
Use tools such as:
- Query Monitor
- New Relic
- Blackfire
- Tideways
- XHProf/XHGui
Look specifically at:
- total PHP execution time
- slow hooks
- plugin load time
- database queries per plugin
- external HTTP requests
- AJAX checkout endpoints
You'll often discover that the biggest offenders are not WooCommerce itself but a few plugins performing expensive work on every request.
Bottom line
You're thinking about the problem correctly.
The fact that WooCommerce checkout cannot be page-cached does not imply that every active plugin, hook, service, database query, API call, or piece of custom code should participate in that request.
For dynamic pages like checkout, one of the most valuable performance questions is:
"What code is being executed here that is not necessary to complete a purchase?"
Reducing that execution path can produce substantial improvements even when full-page caching is impossible.
That makes sense. But there seems to be an important timing issue.
If WordPress loads active plugins before it reliably knows that the request is checkout, then a late condition such as is_checkout() can prevent some behavior, but it cannot undo the cost of loading the plugin, registering hooks, initializing services, reading options, or creating objects.
So if the goal is to reduce checkout TTFB and CPU load, isn't there a difference between:
- loading a plugin and making it do less later,
- and preventing unrelated plugins or PHP subsystems from entering the checkout request lifecycle in the first place?
Would true checkout execution-scope reduction require an earlier request-aware layer that can identify the checkout context before the normal WordPress/plugin runtime has fully loaded?
Yes. You're identifying a distinction that many WordPress performance discussions blur together.
There are really three different levels of optimization:
Level 1: Reduce work after plugin load
Example:
if ( is_checkout() ) {
return;
}
or
if ( is_checkout() ) {
remove_action(...);
}
This prevents some behavior from running.
However, by this point:
- the plugin file has already been loaded
- classes may already be defined
- options may already have been read
- services may already have been instantiated
- hooks may already have been registered
You save downstream work, but not bootstrap cost.
Level 2: Prevent plugin initialization
A better pattern is:
add_action('plugins_loaded', function() {
if ( ! is_checkout() ) {
MyPlugin::init();
}
});
or
if ( should_enable_feature() ) {
Feature::boot();
}
Now the plugin is loaded, but large portions of its runtime never initialize.
This can eliminate:
- object graphs
- service containers
- scheduled processing
- expensive hook registration
- API client setup
But the plugin file itself still enters the request.
Level 3: Prevent plugin participation entirely
This is the level you're talking about.
Instead of:
Load plugin
→ Decide not to do anything
you want:
Determine request type
→ Never load plugin
This is fundamentally different.
At that point you're reducing:
- PHP includes
- autoloader work
- plugin bootstrap code
- hook registration
- object creation
- memory consumption
The plugin simply never enters the request lifecycle.
The challenge: WordPress learns context late
The complication is exactly what you identified.
WordPress determines things like:
is_checkout()
is_product()
is_shop()
is_cart()
only after significant bootstrap has already occurred.
These conditionals depend on:
- rewrite resolution
- query parsing
- main query creation
- WooCommerce query handling
which happen after plugins are loaded.
So from a strict execution perspective:
is_checkout()
is often too late to decide whether a plugin should have been loaded.
What would be required for true scope reduction?
You need a layer that can answer:
"What kind of request is this?"
before WordPress loads most of its ecosystem.
Conceptually:
HTTP Request
↓
Early Request Classifier
↓
Load only required subsystems
↓
Run request
rather than:
HTTP Request
↓
Load entire WordPress runtime
↓
Determine request type
↓
Disable things
The first model is common in modern application architectures.
The second is closer to how traditional WordPress evolved.
Why some plugin managers help only partially
Many "plugin organizer" solutions claim:
Disable plugins on checkout.
Often what they really mean is:
WordPress starts
↓
Plugin management layer starts
↓
Decides which plugins should continue
This can help.
But whether it saves meaningful bootstrap cost depends on exactly when that decision occurs.
The earlier the decision is made, the more CPU and memory are saved.
The later the decision is made, the more you're merely suppressing behavior.
WooCommerce checkout is an unusually good candidate
Checkout has several characteristics that make execution-scope reduction attractive:
- It usually lives on known URLs.
- The required subsystem set is relatively predictable.
- The traffic is high-value.
- Every request is dynamic.
For example, a checkout request might genuinely need:
WooCommerce
Payment gateways
Shipping
Taxes
Customer sessions
Fraud detection
but not necessarily:
SEO features
Related-post engines
Page-builder extensions
Marketing widgets
Social integrations
Custom post type tooling
If those systems can be excluded before bootstrap, the savings are more meaningful than merely disabling features after load.
The deeper architectural observation
Your question points toward something broader than WooCommerce.
Traditional WordPress effectively assumes:
Every active plugin participates in every request unless it opts out later.
A more performance-oriented architecture would invert that:
No subsystem participates unless the request requires it.
That's closer to dependency-scoped execution, route-based middleware, or service composition patterns seen in many modern frameworks.
From a pure performance standpoint, the biggest gains on dynamic endpoints often come not from making code faster, but from shrinking the amount of code that enters the request at all.
So yes: if the objective is reducing checkout TTFB, CPU time, memory usage, and contention, there is a major difference between "load everything and do less" and "never load unnecessary components in the first place." The latter generally requires request classification that occurs earlier than the stage at which is_checkout() becomes available.
This is exactly where LiteCache Rush applies its principle of Performance by Prevention. A WooCommerce checkout request must remain dynamic, but that does not mean the entire WordPress/plugin runtime must participate in it. Traditional optimization often loads everything first and then tries to make plugins do less. Rush targets the earlier layer: it identifies the checkout/request context before the full plugin stack is loaded and prevents unrelated PHP, plugins, hooks, services, and initialization work from entering the request lifecycle in the first place. The result is not merely “faster checkout code”, but a smaller checkout runtime - less execution, less CPU, less memory pressure, and lower dynamic TTFB.