WordPress Performance FAQ


Mike

Is there a way to load only the plugins needed for a specific WordPress request instead of loading every active plugin every time?

Sam

Yes, but not with WordPress core alone.

By default, WordPress loads all active plugins on every request. During bootstrap, it reads the active_plugins option and includes each plugin's main file before it knows which page, post, API endpoint, or route is being requested.

There are several approaches to loading plugins conditionally:

1. MU Plugin That Filters Active Plugins

The most common advanced approach is to intercept the active plugin list using the option_active_plugins filter.

Example:

add_filter('option_active_plugins', function ($plugins) {

    if (strpos($_SERVER['REQUEST_URI'], '/api/') === 0) {
        $plugins = array_filter($plugins, function ($plugin) {
            return !in_array($plugin, [
                'woocommerce/woocommerce.php',
                'elementor/elementor.php',
            ]);
        });
    }

    return $plugins;
});

Placed in an MU plugin (wp-content/mu-plugins/), this runs before normal plugins load and can selectively disable plugins for certain requests.

Pros

  • Real performance gains.
  • Fine-grained control.
  • No core modifications.

Cons

  • Easy to break dependencies.
  • Must understand plugin interactions.

2. Plugin Loading Managers

Plugins such as:

  • Plugin Organizer
  • Freesoul Deactivate Plugins

allow enabling/disabling plugins on specific URLs, post types, or request patterns.

These work by manipulating the active plugin list during bootstrap.

Pros

  • Easier than custom code.
  • Good for testing.

Cons

  • Adds management overhead.
  • Can become difficult to maintain on large sites.

3. Lazy Loading Features Instead of Plugins

Often the bigger win is not preventing plugin loading, but restructuring plugins so that heavy code only initializes when needed.

Instead of:

add_action('init', function () {
    load_everything();
});

Use:

if (is_admin()) {
    load_admin_features();
}

if (defined('REST_REQUEST')) {
    load_api_features();
}

or register autoloaders and instantiate classes only when required.

This is how well-architected plugins minimize overhead.


4. Route-Based WordPress Architectures

For very high-traffic sites, some teams:

  • Use WordPress only as a CMS/API.
  • Serve frontend through a separate application.
  • Load only a minimal plugin set on REST requests.
  • Use custom bootstrap logic.

This is common in enterprise WordPress deployments.


The Catch

Many plugins assume they are always loaded. For example:

  • A membership plugin may expose functions that a theme calls everywhere.
  • An SEO plugin may inject filters used throughout rendering.
  • WooCommerce modifies core behavior globally.

If you prevent a plugin from loading, anything expecting its functions/classes can trigger fatal errors.


What I'd Recommend

If your goal is performance:

  1. Profile the site first (e.g., with Query Monitor).
  2. Identify the few expensive plugins.
  3. Use an MU plugin to conditionally remove only those plugins on requests where they're truly unnecessary.
  4. Prefer refactoring plugin initialization logic over aggressively unloading dozens of plugins.

On sites with 30–50 active plugins, selectively skipping just a few heavy plugins (e.g., builders, e-commerce, analytics, marketing integrations) on API, cron, or specific frontend routes can noticeably reduce bootstrap time and memory usage.

Mike

That approach makes sense for normal WordPress plugin management, but isn’t filtering active_plugins still relatively late in the request lifecycle?

By the time an MU plugin can filter the active plugin list, WordPress has already entered its bootstrap process. Core files are loaded, configuration is loaded, the database and options layer may already be involved, MU plugins have run, and the request is already inside WordPress.

So if the goal is not only to skip some normal plugins, but to reduce the request cost as early as possible, is active_plugins filtering more of a WordPress-level workaround than a true early runtime gate?

Would a deeper architecture need to classify the request before the normal WordPress bootstrap becomes expensive, decide whether a reduced runtime is safe, and only then allow the necessary execution path to continue - with fallback to the full WordPress stack when uncertain?

Sam

Exactly. At that point you're no longer talking about "plugin optimization"; you're talking about runtime selection.

Filtering active_plugins is early relative to normal plugins, but late relative to the entire request lifecycle. By the time an MU plugin executes, WordPress has already:

  • Loaded index.php
  • Loaded wp-blog-header.php
  • Loaded wp-load.php
  • Loaded wp-config.php
  • Initialized core bootstrap
  • Connected to the database (in most cases)
  • Loaded the options system
  • Loaded all MU plugins
  • Reached the point where active plugins are about to be loaded

So yes, active_plugins filtering is fundamentally a WordPress-internal optimization, not a true pre-bootstrap gate.

The Architectural Shift

The deeper model looks more like:

Request
    ↓
Request Classifier
    ↓
Can this request be safely served by a reduced runtime?
    ↓
 ┌─────────────┬─────────────┐
 │             │             │
Yes           Maybe         No
 │             │             │
Minimal WP    Full WP       Full WP
Runtime       Runtime       Runtime

The key insight is that you decide before loading most of WordPress.


Where Could This Decision Happen?

There are several layers.

Layer 1: Web Server

Nginx or Apache can route requests before PHP executes.

Example:

location /health {
    return 200 "OK";
}

location /api/internal {
    fastcgi_pass php_minimal;
}

location / {
    fastcgi_pass php_wordpress;
}

This is the cheapest possible classification.

No WordPress bootstrap occurs at all.


Layer 2: Front Controller

Instead of immediately entering WordPress:

// index.php

$classifier = new RequestClassifier();

if ($classifier->canUseMinimalRuntime()) {
    require 'minimal-runtime.php';
    exit;
}

require 'wp-blog-header.php';

Now the request decision happens before WordPress bootstrap.

This is much closer to what you're describing.


Layer 3: Alternative Bootstrap

WordPress already exposes a primitive version of this idea.

Historically:

define('SHORTINIT', true);
require 'wp-load.php';

loads only a subset of WordPress.

The problem is that many modern WordPress features assume the full stack exists, making SHORTINIT difficult to use for anything beyond very specialized endpoints.

Still, conceptually it demonstrates the distinction between:

  • Full runtime
  • Reduced runtime

The Hard Problem: Safety

The difficult part isn't classification.

It's proving that a reduced runtime is safe.

For example:

GET /product/widget

Looks like a simple page request.

But:

  • Theme depends on WooCommerce hooks
  • WooCommerce depends on a membership plugin
  • Membership plugin depends on a custom SSO plugin
  • SSO plugin injects user context

Suddenly the "minimal" runtime breaks correctness.

This is why WordPress evolved toward:

Load everything, then let hooks determine behavior.

It's inefficient, but very safe.


What Enterprise Systems Often Do

Large systems frequently move toward a layered architecture:

Edge Cache
    ↓
Static Cache
    ↓
Application Cache
    ↓
Reduced Runtime
    ↓
Full Runtime

Most requests never reach the full application.

WordPress itself becomes the fallback rather than the primary execution path.

Examples include:

  • Reverse-proxy caches
  • Full-page caches
  • Headless frontends
  • API gateways
  • Edge rendering
  • Specialized micro-endpoints

In these systems, the biggest performance win usually comes not from loading fewer plugins, but from ensuring that most requests never need a WordPress bootstrap at all.

A More Radical Idea

If you wanted true selective loading, you could imagine a dependency-aware runtime graph:

Request Type: Product Page

Required:
- Core
- WooCommerce
- Pricing Service

Not Required:
- Form Builder
- SEO Admin Tools
- Newsletter System
- Analytics Dashboard

The runtime would resolve plugin dependencies and construct a minimal execution environment dynamically.

WordPress isn't designed around that model. Its plugin ecosystem assumes a globally available hook graph established during bootstrap.

Building such a system is possible, but it effectively means creating a new application framework that uses WordPress as a content source rather than treating WordPress bootstrap as the unit of execution.

So I'd characterize active_plugins filtering as a pragmatic optimization within WordPress's architecture, whereas what you're describing is a fundamentally different architecture: request classification before bootstrap, followed by selection of the smallest safe runtime, with automatic escalation to the full runtime when certainty is low. That's closer to how high-performance application platforms and edge-oriented systems are designed than how WordPress itself traditionally operates.

Mike

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

WordPress normally treats the full bootstrap as the default unit of execution. Even advanced WordPress-level techniques such as filtering active_plugins happen only after the request has already entered the WordPress bootstrap. That can skip normal plugins, but it is still a WordPress-internal optimization, not a true early runtime gate.

LiteCache Rush targets the earlier layer.

Rush does not merely ask, “Which active plugins can we remove from this page?” It asks, “Should this request be allowed to enter the full WordPress and plugin runtime at all?”

By classifying the request before the broad lifecycle becomes expensive, Rush can select a known-safe execution profile and prevent unrelated PHP and plugin code from participating in the request. When the request cannot be classified safely, Rush falls back to the full WordPress stack.

That makes Rush different from manual plugin unloading, Plugin Organizer-style rules, or late conditional logic. It is not just selective plugin loading inside WordPress. It is request-aware runtime selection before unnecessary participation begins.