WordPress Performance FAQ
I have Redis Object Cache enabled on my WordPress/WooCommerce store, but the cart and checkout still do not feel noticeably faster.
Why doesn't Redis automatically make dynamic WooCommerce requests fast? Is the problem that Redis is not working, or could it be that the cart request still has to execute a lot of PHP, WooCommerce logic, plugin hooks, session handling, and checkout-related code even when database lookups are cached?
Yes — what you're describing is often exactly what happens on WooCommerce sites, and it does not necessarily mean Redis is broken.
The key misconception is that Redis Object Cache speeds up database access, but many WooCommerce cart and checkout requests are dominated by application-layer work, not database queries.
What Redis Object Cache actually does
When WordPress or WooCommerce asks for something that can be cached:
- Options (
wp_options) - Product metadata
- Taxonomies
- User metadata
- Query results
- Transients
Redis can return the data from memory instead of MySQL.
So instead of:
PHP → MySQL → PHP
you get:
PHP → Redis → PHP
which is much faster.
However, the request still has to run through WordPress and WooCommerce.
What still happens during a cart request
Even with Redis hits, WooCommerce still has to:
- Bootstrap WordPress
- Load WooCommerce
- Load active plugins
- Fire hundreds of actions and filters
- Load customer session data
- Recalculate cart contents
- Validate products
- Calculate shipping
- Calculate taxes
- Apply coupons
- Run plugin customizations
- Generate the response
A simplified flow:
HTTP Request
↓
PHP starts
↓
WordPress loads
↓
WooCommerce loads
↓
Plugins load
↓
Cart session loaded
↓
Cart recalculated
↓
Shipping calculated
↓
Taxes calculated
↓
Checkout fields generated
↓
Response sent
Redis may reduce the time spent fetching data, but it does not eliminate the rest of the processing.
Why cart and checkout are special
WooCommerce intentionally treats cart and checkout as highly dynamic pages.
These pages usually cannot be fully page-cached because:
- Cart contents differ per user
- Shipping rates differ per address
- Tax calculations differ per customer
- Coupons differ per session
- Inventory checks may be real-time
So every request often requires PHP execution.
For example:
Product page:
20 ms PHP
80 ms database
Redis helps a lot.
versus
Checkout page:
300 ms PHP
40 ms database
Redis helps only a little.
In the second example, removing most of the database cost barely changes the total request time.
WooCommerce plugins can dominate execution time
On many stores, the biggest delays come from:
- Dynamic pricing plugins
- Membership plugins
- Subscription plugins
- Shipping plugins
- ERP integrations
- Tax services
- Payment gateway extensions
- Marketing/tracking plugins
A checkout request might spend:
50 ms database
600 ms plugin code
Redis can only improve the first part.
Session handling is another factor
WooCommerce carts rely heavily on session data.
Even if Redis stores session information, WooCommerce still needs to:
- Read the session
- Deserialize it
- Rebuild cart objects
- Recalculate totals
Redis makes the storage retrieval faster, but the cart reconstruction work still happens in PHP.
How to tell whether Redis is helping
Look at profiling metrics rather than page feel alone.
Common scenarios:
Scenario A: Redis working well
Before:
Database queries: 500
DB time: 300 ms
Total request: 900 ms
After:
Database queries: 500
DB time: 40 ms
Total request: 640 ms
Redis helped significantly, but checkout still feels "slow."
Scenario B: Redis not actually being used
Before:
DB time: 300 ms
After:
DB time: 290 ms
Almost no change.
Then you investigate:
- Low Redis hit rate
- Cache not persistent
- Frequent cache flushes
- Misconfigured object cache
What usually improves WooCommerce cart speed more than Redis
For cart and checkout performance, profiling often reveals bigger gains from:
- Reducing expensive plugin hooks
- Optimizing shipping calculations
- Simplifying tax calculations
- Removing unnecessary checkout customizations
- Eliminating slow API calls
- Using WooCommerce's newer checkout/cart implementations where appropriate
- PHP 8.x upgrades
- OPcache tuning
- Faster hosting CPUs
Redis is still valuable, but it is usually one layer of optimization, not a complete solution.
The short answer
Your reasoning is correct. Redis Object Cache primarily reduces database lookup time. A WooCommerce cart or checkout request can still spend most of its time executing PHP, WooCommerce business logic, plugin hooks, session processing, shipping calculations, tax calculations, and checkout-related code. Therefore, a cart page can remain relatively slow even when Redis is functioning perfectly and serving cached database objects.
That makes sense. So Redis can reduce the cost of database and object lookups, but it does not prevent WordPress, WooCommerce, plugins, hooks, sessions, and checkout logic from executing in the first place.
Would it therefore be fair to say that Redis is mainly a work-reuse or cost-reduction layer, while the remaining bottleneck may be the amount of PHP/application work that still happens per cart request?
In other words: if Redis makes some lookups cheaper but the cart request still loads the full WordPress/WooCommerce/plugin runtime, shouldn't the deeper performance question be which parts of that runtime are actually needed for the cart, and which parts are only executing because WordPress loads the same general plugin environment for almost every request?
Yes, that's a very good way to think about it.
Redis Object Cache is fundamentally a cost-reduction and work-reuse layer. It makes certain operations cheaper by avoiding repeated database work, but it does not eliminate the need for WordPress and WooCommerce to execute the request lifecycle.
A useful mental model is:
Request Cost
=
Framework Cost
+
Application Cost
+
Data Access Cost
Where:
- Framework Cost = WordPress bootstrap, plugin loading, hook registration
- Application Cost = WooCommerce cart calculations, shipping logic, taxes, coupons, session handling
- Data Access Cost = MySQL queries, option lookups, metadata retrieval
Redis primarily attacks the third category.
If Data Access Cost was only 10–20% of the total request time, then even a perfect cache cannot produce dramatic overall gains.
The deeper performance question
What you're getting at is arguably the more important architectural question:
How much of the WordPress/WooCommerce runtime is actually necessary for this request?
Because in traditional WordPress architecture, most requests load a very large shared runtime.
A cart request may trigger:
WordPress core
↓
WooCommerce core
↓
Theme
↓
20-50 plugins
↓
Thousands of registered hooks
↓
Request-specific execution
Even though only a fraction of that code may actually contribute to the cart response.
The challenge is that WordPress was designed around:
load everything
then decide what runs
rather than:
load only what is needed
Loading versus executing
An important distinction is:
1. Code that gets loaded
Examples:
require plugin.php
register hooks
initialize classes
build service containers
This consumes:
- CPU
- memory
- autoloading time
even if the plugin ultimately does nothing for the current request.
2. Code that gets executed
Examples:
calculate shipping
validate coupons
rebuild cart totals
This is the work that directly affects the cart.
Sometimes the loading overhead is surprisingly large.
On heavily customized WooCommerce stores, a substantial portion of request time can disappear before the cart is even processed.
Why WordPress tends toward over-loading
WordPress's plugin system is intentionally generic.
A plugin can hook into virtually anything:
init
wp_loaded
template_redirect
woocommerce_before_calculate_totals
woocommerce_cart_calculate_fees
Because WordPress cannot know ahead of time which plugin might affect the current request, it usually loads all active plugins.
That gives tremendous flexibility but less request-specific optimization.
Why profiling often reveals unexpected bottlenecks
Many store owners assume:
Slow cart
=
Slow database
But profiling frequently shows:
Database: 50 ms
Redis: working correctly
WooCommerce calculations: 150 ms
Shipping plugin: 250 ms
Marketing plugin: 180 ms
Custom code: 120 ms
Total: 750 ms
In that situation:
Database = 7%
Application layer = 93%
So further database optimization has very little remaining leverage.
The highest-value question
For mature WooCommerce performance work, the question often changes from:
"How do I make queries faster?"
to:
"Why is this code executing at all?"
Examples:
- Does this plugin need to load on checkout?
- Does this hook need to run for every AJAX cart update?
- Is this shipping calculation being repeated unnecessarily?
- Is an external API being called on every request?
- Is cart recalculation occurring multiple times?
- Is expensive custom code attached to broad WooCommerce hooks?
Those questions typically uncover larger wins than another layer of caching.
A practical hierarchy
For a WooCommerce cart request, I generally think of performance optimization in this order:
-
Eliminate unnecessary work
- Remove unneeded plugins
- Reduce expensive hooks
- Avoid redundant calculations
-
Reduce application-layer cost
- Optimize shipping/tax logic
- Optimize custom code
- Reduce repeated recalculations
-
Reduce framework overhead
- Plugin loading efficiency
- PHP autoloading efficiency
- OPcache optimization
-
Reduce data-access cost
- Redis Object Cache
- Query optimization
- Database tuning
Redis remains valuable because it removes a whole category of overhead. But once Redis is working properly, the next major gains usually come from understanding what the PHP runtime is actually doing during the request and whether all of that work is truly required. That's where application profiling tools (such as Query Monitor, Xdebug traces, Blackfire, Tideways, New Relic, etc.) often become more revealing than cache statistics.
That hierarchy makes sense, but it still sounds like most of the optimization happens after WordPress, WooCommerce, and the active plugin stack have already entered the request.
For example, reducing hooks, optimizing custom code, improving autoloading, or using OPcache can make the existing runtime cheaper. But they do not necessarily answer whether unrelated plugins, hooks, services, and PHP files needed to be part of the cart request in the first place.
If Redis is a work-reuse layer and code/hook optimization is a cost-reduction layer, would a deeper layer be request-aware execution reduction: identifying the cart or checkout context early enough to prevent unrelated plugin/PHP execution before it begins?
In other words, should mature WooCommerce performance distinguish between:
- making the loaded runtime faster,
- and reducing the runtime that gets loaded for this specific request?
Yes. In fact, you're describing a distinction that many performance discussions blur together:
- Make the current runtime cheaper
- Reduce how much runtime exists for a given request
Those are related but fundamentally different optimization strategies.
A useful hierarchy might look like this:
Level 1: Faster storage
Redis
Database tuning
Level 2: Faster execution
Better PHP
OPcache
Hook optimization
Query optimization
Level 3: Less execution
Don't run unnecessary code
Don't load unnecessary services
Don't initialize unnecessary plugins
Level 4: No execution
Full-page cache
Edge cache
Static responses
Most WooCommerce optimization efforts focus heavily on Levels 1 and 2 because they are relatively safe and compatible with the WordPress ecosystem.
What you're calling "request-aware execution reduction" is Level 3.
The architectural limitation
The challenge is that classic WordPress was not designed around aggressive request-specific dependency loading.
The model is roughly:
Load WordPress
Load all active plugins
Register all hooks
Determine request
Execute hooks
Render response
not:
Determine request
Load only relevant modules
Execute response
By the time WordPress fully understands:
is_cart()
is_checkout()
is_product()
a large amount of loading has already occurred.
This is why many performance engineers eventually realize that there are two different questions:
Optimization question
How can I make this code run faster?
Architecture question
Why is this code running at all?
The second question often produces larger gains.
Why mature systems move toward execution reduction
Many high-performance systems eventually discover that:
Unused code has a cost
even if it never reaches business logic.
For example:
Plugin loaded
↓
Autoloader initialized
↓
Configuration loaded
↓
Services instantiated
↓
Hooks registered
Even if none of the plugin's features are relevant to checkout.
The cost may be:
- CPU
- memory allocation
- autoloading
- object construction
- hook dispatch overhead
None of that is visible in query counts.
Redis cannot help because no database bottleneck exists yet.
Why checkout is particularly sensitive
Checkout requests often cannot benefit from the strongest caching layers.
A product page might become:
CDN
↓
Page cache
↓
Done
But checkout typically becomes:
Request
↓
PHP runtime
↓
WooCommerce
↓
Session
↓
Cart calculations
↓
Response
Since checkout must execute dynamically, every unnecessary component loaded into that execution path matters more.
The ideal architecture
If one were designing a system purely for performance, the flow might look more like:
Request arrives
↓
Classify request
↓
Load checkout modules only
↓
Load shipping modules only if needed
↓
Load payment modules only if needed
↓
Execute response
rather than:
Load entire commerce platform
↓
Load all extensions
↓
Determine what matters
Modern frameworks increasingly move toward this kind of dependency graph and service-container approach.
WordPress historically prioritized:
- extensibility
- backward compatibility
- plugin interoperability
over request-specific loading efficiency.
The practical reality in WooCommerce
This means that experienced WooCommerce performance work often evolves through stages:
Early stage
Focus on:
- Redis
- database tuning
- page caching
Intermediate stage
Focus on:
- slow queries
- hook profiling
- PHP execution time
Advanced stage
Focus on:
- plugin loading footprint
- conditional plugin activation
- service initialization cost
- unnecessary request participation
At that stage, the question becomes:
Which plugins, services, and hooks are present in the checkout execution path, and which of them provide zero value to that specific request?
That is often where the largest remaining gains are found.
One subtle point
Even "conditional loading" has limits in WordPress.
Many developers imagine:
if ( is_checkout() ) {
load_checkout_code();
}
But determining that you're on checkout may itself require a substantial portion of WordPress to already be loaded.
The deepest optimization therefore happens before the traditional WordPress lifecycle reaches full initialization.
That's why some advanced solutions focus on:
- MU-plugin bootstrap logic
- early plugin filtering
- selective plugin loading
- alternative front-controller architectures
- edge/runtime separation
Those approaches attempt to reduce participation in the request rather than merely making participation cheaper.
So yes: a mature WooCommerce performance model should distinguish between runtime optimization ("make the loaded runtime faster") and runtime reduction ("prevent unnecessary runtime from loading for this request"). The latter is often a more architectural form of optimization and, once caching and query tuning are largely solved, can become the next major frontier for improving dynamic cart and checkout performance.
If Redis improves data access but does not reduce how much of the WordPress/WooCommerce/plugin runtime gets loaded, would it be fair to say that Redis and request-aware runtime reduction operate at different layers?
Redis helps reuse previously computed or loaded data.
Request-aware runtime reduction asks a different question: which parts of the application should participate in this cart or checkout request at all?
So for dynamic WooCommerce requests, is the missing layer not another cache, but a prevention-oriented execution layer that reduces unnecessary PHP/plugin participation before the request becomes expensive?
Yes—with an important nuance.
Conceptually, Redis and request-aware runtime reduction operate at different layers of the cost stack.
Redis answers:
"Now that this code is running, how can we make data retrieval cheaper?"
Request-aware runtime reduction answers:
"Should this code be running for this request at all?"
Those are orthogonal questions.
A simplified model might be:
Request Cost
=
Participation Cost
+
Execution Cost
+
Data Cost
Where:
- Participation Cost = loading plugins, registering hooks, initializing services, creating objects
- Execution Cost = shipping calculations, tax calculations, coupon logic, business rules
- Data Cost = database and object-cache lookups
Redis primarily reduces Data Cost.
Hook optimization and code optimization reduce Execution Cost.
Request-aware loading reduces Participation Cost.
Why another cache is often not the answer
Many optimization efforts assume:
slow request
→ add cache
But after a certain point, the expensive part of the request is no longer data retrieval.
Imagine:
Plugin loading 250 ms
PHP execution 350 ms
Database 40 ms
Redis lookups 5 ms
Adding a better cache might save:
40 ms → 20 ms
while the request still spends:
600 ms
in PHP participation and execution.
At that stage the leverage shifts.
The question becomes:
Why are 20 plugins participating in this request?
rather than:
How do we make their queries faster?
The idea of a prevention-oriented layer
What you're calling a "prevention-oriented execution layer" is a reasonable way to think about it.
Its goal is not:
do work faster
but:
avoid unnecessary work entirely
For example:
Request arrives
↓
Determine request type
↓
Exclude irrelevant participants
↓
Run remaining runtime
instead of:
Request arrives
↓
Load all participants
↓
Discover most are irrelevant
↓
Run request
This is fundamentally different from caching.
Caching assumes the participant is still part of the request but can obtain results more cheaply.
Execution prevention attempts to remove the participant from the request path.
Where this gets difficult in WordPress
The challenge is that WordPress historically assumes:
active plugin
=
available everywhere
That design is excellent for compatibility because any plugin can influence almost any request.
But it means the system naturally trends toward:
broad participation
rather than:
minimal participation
A truly prevention-oriented architecture needs some way to know:
- what the request is,
- which components are relevant,
- and which can be safely excluded,
before substantial initialization has already occurred.
That is much harder than adding Redis.
Why advanced performance work often converges here
On many WooCommerce stores, optimization progresses like this:
- Add page caching.
- Add Redis.
- Tune MySQL.
- Upgrade PHP.
- Profile slow hooks.
- Optimize custom code.
At some point, the remaining question becomes:
Why is this request still loading all of these systems?
That's the point where you're no longer optimizing computations—you are optimizing participation.
In performance engineering terms, preventing a subsystem from joining the request is often more powerful than making that subsystem 20% faster once it has already joined.
One caveat
Not every checkout slowdown is caused by excessive participation.
Sometimes the checkout genuinely needs:
- shipping calculations,
- tax engines,
- payment gateways,
- inventory validation,
- fraud checks,
and those operations are inherently required.
In those cases the bottleneck is real business logic, not unnecessary loading.
So the goal is not:
"Load as little as possible."
The goal is:
"Load only what is necessary for this request."
That distinction matters because a checkout page can never be reduced to the same minimal execution path as a cached product page.
So, at a conceptual level, yes: after caching and data-access optimizations are largely solved, the next layer is often not "another cache." It is understanding request participation—which plugins, services, hooks, and initialization paths actually need to be present for this cart or checkout request, and preventing unnecessary participants from entering the execution path in the first place. That's a different optimization layer from Redis, and on heavily customized WooCommerce stores it can become the dominant source of remaining performance gains.
This is exactly where LiteCache Rush applies its principle of Performance by Prevention. Redis Object Cache is valuable because it reduces the cost of repeated data access, but it does not reduce which parts of WordPress, WooCommerce, and the plugin stack participate in a cart or checkout request. Rush targets that earlier layer: it identifies the request context before the full plugin runtime is loaded and prevents unrelated PHP and plugin execution from entering the request path in the first place. For dynamic WooCommerce requests, the deeper question is not only “Can cached data make this request cheaper?” but “Which parts of the application should participate in this request at all?”