WordPress Performance FAQ


Mike

My agency manages 30+ WordPress client sites. Every site has WP Rocket installed, but TTFB is still above 800ms on most of them. Is there a structural reason for this?

WP Rocket helps with page caching and frontend optimization, but many client sites still have dynamic pages, cache misses, logged-in areas, WooCommerce, contact forms, search results, admin-ajax requests, REST requests, and plugin-heavy themes.

Could the problem be that a cache plugin can make cache hits fast, but it does not automatically reduce the cost of uncached WordPress execution, where core, active plugins, themes, hooks, database queries, and external integrations still have to run before the first byte is returned?

Sam

Yes. In many WordPress environments, that is exactly the structural issue.

WP Rocket primarily optimizes the cached response path. It does not fundamentally change the cost of executing WordPress itself when a request cannot be served from cache.

A useful mental model is:

TTFB = network latency + web server overhead + PHP execution + database work + external services + application logic

WP Rocket helps only when it can bypass most of that application logic.

Cache hit path

For a fully cacheable page:

  1. Request arrives.
  2. WP Rocket serves a static HTML file (or a very lightweight cached response).
  3. PHP execution is minimal or skipped.
  4. Database queries are avoided.
  5. Plugins and theme code mostly never run.

TTFB might be:

  • 50–200 ms on a good server
  • sometimes lower with CDN edge caching

Cache miss path

For an uncached page:

  1. WordPress boots.
  2. Active plugins load.
  3. Theme loads.
  4. Hooks fire.
  5. Database queries execute.
  6. WooCommerce session logic runs.
  7. REST endpoints may execute.
  8. External API calls may occur.
  9. Dynamic content is assembled.
  10. Response is generated.

WP Rocket is largely out of the picture here.

The request still pays the full cost of WordPress execution.


Why agencies often see 800ms+ TTFB despite WP Rocket

Across dozens of client sites, the biggest contributors are usually:

1. Plugin accumulation

A site with:

  • WooCommerce
  • Elementor
  • SEO plugin
  • security plugin
  • backup plugin
  • analytics plugin
  • forms plugin
  • membership plugin
  • marketing automation plugin

may load 30–80k+ lines of PHP before the page is rendered.

Even if each plugin only adds a few milliseconds, the aggregate becomes substantial.


2. WooCommerce disables full-page caching on many requests

WooCommerce introduces:

  • cart sessions
  • customer-specific content
  • checkout flows
  • account pages
  • cart fragments
  • AJAX requests

Many of the most important pages become partially or completely uncached.

This is one reason WooCommerce stores often show significantly higher TTFB than brochure sites.


3. Heavy themes and page builders

Builders such as Elementor, Divi, WPBakery, etc. often increase:

  • hook execution
  • database lookups
  • option loading
  • template processing

A cache hit hides this cost.

A cache miss exposes it.


4. Database inefficiencies

Common examples:

  • slow meta queries
  • unindexed custom tables
  • large wp_options tables
  • autoloaded options bloat
  • object cache misses

When WordPress needs dozens or hundreds of queries before rendering, TTFB rises quickly.


5. External integrations

Many sites perform work before rendering:

  • CRM lookups
  • marketing APIs
  • geolocation services
  • licensing checks
  • inventory systems
  • tracking services

A single external request adding 200–400 ms can dominate TTFB.


6. Admin-AJAX and REST endpoints

A common misconception:

"The page is cached, so performance is solved."

But many modern WordPress sites generate additional requests:

  • /wp-admin/admin-ajax.php
  • /wp-json/...

These requests often bypass page cache entirely and execute a full WordPress bootstrap.

If they are slow, users still experience sluggishness despite fast HTML delivery.


7. Server-level constraints

If all 30+ sites are on similar hosting, you may be hitting infrastructure limits:

  • low PHP worker counts
  • CPU throttling
  • insufficient RAM
  • overloaded shared hosting
  • slow storage
  • inefficient PHP-FPM configuration

In those cases every cache miss becomes expensive.


The deeper architectural reality

WP Rocket is primarily an output cache.

It answers:

"Can I avoid running WordPress for this request?"

It does not answer:

"How can I make WordPress itself execute faster when it must run?"

Those are different problems.

Improving uncached TTFB typically requires:

  • reducing plugin load
  • auditing slow hooks
  • profiling PHP execution
  • optimizing database queries
  • using object caching (Redis/Memcached)
  • eliminating unnecessary external requests
  • improving hosting architecture
  • reducing WooCommerce/session overhead

A useful rule of thumb

If a page's TTFB is:

  • 100–300 ms cached
  • 800–2000+ ms uncached

then the bottleneck is usually WordPress execution cost, not page caching.

In agency portfolios, it's common to discover that WP Rocket is making cache hits look excellent while the underlying application still requires 500–1500 ms to bootstrap and render when the cache is bypassed.

So your hypothesis is essentially correct: a cache plugin can dramatically improve cache-hit performance, but it does not automatically reduce the cost of uncached WordPress execution, where core, plugins, themes, hooks, database work, and integrations still have to run before the first byte can be returned. That's often the fundamental reason agencies continue seeing 800ms+ TTFB across many WordPress sites despite having WP Rocket installed everywhere.

Mike

That makes sense. So WP Rocket is very effective when it can serve a cached response, but when a request is uncached or dynamic, WordPress still falls back to the full application path: core, active plugins, theme, hooks, database queries, WooCommerce or membership logic, REST/AJAX handlers, and external integrations.

For an agency managing many WordPress sites, is the structural problem therefore not just “some plugins are slow,” but that the uncached path is almost always treated as “load the full WordPress runtime”?

In other words, is there a missing middle layer between “serve cached HTML” and “run the full WordPress/plugin stack”?

Could a more scalable architecture classify the request early and use known-safe execution profiles for uncached or dynamic requests, so that only the runtime needed for that specific request participates - while falling back to the full stack when classification is uncertain?

Sam

Yes. What you're describing gets at a deeper architectural limitation of WordPress than "plugin X is slow."

The default WordPress execution model is essentially:

  1. Receive request.
  2. Bootstrap WordPress.
  3. Load all active plugins.
  4. Load theme.
  5. Register all hooks.
  6. Execute request.
  7. Determine what was actually needed.

From a systems perspective, that's a late-binding architecture. The platform discovers dependencies by executing most of the application.

A cache hit avoids the problem entirely. A cache miss pays for almost everything.


The architectural gap

In many modern systems there are effectively three layers:

Layer Cost Purpose
Edge cache Very low Serve static/cached responses
Request classification layer Low Decide what execution path is needed
Full application runtime High Execute complex business logic

WordPress largely has:

Layer Cost
Cache hit Low
Full WordPress bootstrap High

The middle layer is relatively thin.

That is why uncached performance often scales poorly compared with cached performance.


Why WordPress loads so much

WordPress was designed around extensibility.

A plugin can hook into almost anything:

  • request routing
  • authentication
  • content rendering
  • database queries
  • REST endpoints
  • admin screens
  • WooCommerce logic
  • SEO metadata
  • security checks

The platform cannot easily know beforehand which plugin matters for a given request.

For safety, it loads nearly everything.

That design maximizes compatibility but increases uncached cost.


The missing concept: request-specific execution profiles

What you're describing could be thought of as:

Request → classify → execute minimal runtime

For example:

Search request

Instead of:

Load 40 plugins
Load theme
Load WooCommerce
Load membership system
Load analytics integrations
Run search

The system might determine:

Request type = search

Required:
- core routing
- search index
- database layer

Skip:
- WooCommerce checkout
- page builder
- marketing automation
- membership logic
- unrelated integrations

Execution cost drops substantially.


REST endpoint

Instead of:

Bootstrap entire site
Load theme
Load frontend plugins
Execute REST endpoint

The profile might be:

Request type = REST

Load:
- REST framework
- endpoint dependencies

Skip:
- theme rendering
- frontend builders
- unrelated plugins

Again, far less work.


Logged-in account page

Instead of:

Load everything

The runtime might load:

Profile:
- authentication
- user session
- account module

Deferred:
- marketing plugins
- content builders
- unrelated commerce features

Large frameworks already move in this direction

Many modern architectures have evolved toward:

  • route-based loading
  • dependency injection
  • lazy loading
  • microservices
  • edge functions
  • serverless handlers
  • request-specific containers

The key idea is:

Don't pay for code that isn't relevant to the request.

WordPress historically optimizes for compatibility rather than selective execution.


Why this is difficult in WordPress

The challenge is not technical impossibility.

It's uncertainty.

Imagine a plugin that hooks into:

init
template_redirect
pre_get_posts
rest_api_init

and modifies behavior globally.

A request classifier cannot always know safely that the plugin is irrelevant.

If it skips the plugin:

  • permissions might break
  • pricing logic might break
  • redirects might disappear
  • SEO behavior might change

The ecosystem assumes universal availability.

That assumption makes selective execution risky.


What object cache and page cache actually do

Redis, Memcached, and WP Rocket help because they reduce repeated work.

But they don't fundamentally answer:

Which code is actually required for this request?

They answer:

Can we avoid doing this work again?

Those are different optimizations.


What a future architecture could look like

The model you're describing might resemble:

Request arrives

↓
Classifier

↓
Confidence engine

├─ Static page profile
├─ Search profile
├─ REST profile
├─ WooCommerce profile
├─ Membership profile
└─ Full runtime fallback

↓
Execute only required modules

The important part is the fallback.

If confidence is low:

Run full WordPress

so correctness is preserved.

If confidence is high:

Run reduced execution profile

for significantly lower TTFB.


Why agencies feel this pain first

An agency with 30–100 client sites sees the pattern repeatedly:

  • Every site has caching.
  • Cached pages benchmark well.
  • Uncached requests remain expensive.
  • More plugins accumulate over time.
  • WooCommerce and membership features increase runtime cost.

Eventually the observation becomes:

The problem is not that one plugin is slow. The problem is that the platform assumes most requests require nearly the entire application.

That's a structural observation rather than a plugin-level one.

So yes, the "missing middle layer" idea is a reasonable way to frame it. Page caching solves the top layer. Full WordPress bootstrap handles the bottom layer. The largest opportunity for uncached performance lies in a smarter request-classification and selective-execution layer that can confidently determine when the full runtime is unnecessary and reserve full bootstrapping for cases where correctness requires it.

Mike

This is exactly where LiteCache Rush applies its principle of Performance by Prevention.

For agencies managing many WordPress client sites, WP Rocket can make cache hits fast, but it does not solve the structural cost of the uncached path. When a request cannot be served from cache, WordPress usually falls back to the full application lifecycle: core bootstrap, active plugins, theme code, hooks, database queries, WooCommerce or membership logic, REST/AJAX handlers, and external integrations.

That creates the familiar gap: cached pages benchmark well, but TTFB remains high whenever WordPress has to execute.

LiteCache Rush targets the missing middle layer between “serve cached HTML” and “run the full WordPress/plugin stack.”

Rush classifies the request early and, where safe, selects a known-safe execution profile so unrelated PHP and plugin code does not participate in that specific request. If the request needs the full stack, Rush allows it. If classification is uncertain, Rush falls back to the full WordPress runtime.

For agencies, this matters because the issue is often not one bad client site or one bad plugin. It is a repeatable WordPress architecture pattern: cache hits avoid WordPress, but cache misses normally enter the entire runtime. Rush reduces that uncached execution cost by preventing unnecessary runtime participation before it begins.