---
title: "Plugin Bloat: How To Decide What To Remove Without Breaking The Site"
url: https://hostmy.blog/wordpress-plugin-bloat/
date: 2026-09-11
modified: 2026-09-03
lang: en
author: "Aditya Sharma"
description: "Plugin count is a bad metric. Here is how to measure what each plugin actually costs, and how to remove one without losing content."
categories:
  - "WordPress"
image: https://hostmy.blog/wp-content/uploads/2026/09/hmb-card-1854-1024x538.jpg
word_count: 1612
---

# Plugin Bloat: How To Decide What To Remove Without Breaking The Site

"How many plugins is too many" is the wrong question, and it is the one everybody asks.

Thirty small plugins that each register one hook and load nothing on the front end will cost less than a single page builder addon pack that enqueues eleven stylesheets on every page. Counting plugins tells you almost nothing. Measuring what each one loads on a request tells you everything.

Here is how to do the measuring, and then how to remove something without discovering three weeks later that four hundred posts have a broken shortcode in them.

## A plugin costs you in six specific places

Understanding where the cost lands is what makes the removal decision obvious later.

| Cost | Where it shows up | How to see it |
| ---- | ----------------- | ------------- |
| PHP executed on every request | Server response time, TTFB | Query Monitor, timing an uncached URL |
| Database queries per page | Response time, database load | Query Monitor query count by component |
| Autoloaded options | Memory on every request, including admin | A query against the options table |
| Front-end CSS and JS | Page weight, render blocking | View source, or the network panel |
| Scheduled events | Background load, cron congestion | `wp cron event list` |
| Update and license checks | Slow admin, outbound HTTP on page loads | Query Monitor HTTP API panel |

The last one is underrated. A plugin that phones home on `admin_init` without caching the result makes every admin page load wait on somebody else's server. That is invisible to visitors and painful to whoever runs the site.

## Measure first, with three commands and one plugin

Install Query Monitor on staging, not production, and load a page as a logged-out user would see it. It attributes queries, hooks, HTTP calls and enqueued assets to individual components. That attribution is the whole point, because guessing which plugin is heavy is unreliable.

Alongside it, three things worth knowing from the command line:

`# What is actually active, with versions and pending updates
wp plugin list --fields=name,status,version,update

# Total autoloaded data, loaded into memory on every request
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS mb, COUNT(*) AS rows_count \
FROM $(wp db prefix)options WHERE autoload IN ('yes','on','auto-on','auto');"

# Scheduled events, grouped so you can see who owns the noise
wp cron event list --fields=hook,recurrence,next_run_relative`

Autoload size is the number people miss. WordPress loads every autoloaded option on every request, so a plugin storing large cached payloads there taxes the whole site including pages that never use the plugin. The effect on real-world speed is covered in [Core Web Vitals in the order that moves the number](/core-web-vitals-wordpress/).

## Sort every plugin into one of five buckets

Once you have measurement, the decisions sort themselves.

**Bucket one: inactive.** Deactivated plugins still sit in the filesystem and still need to be patched, because a vulnerable file can sometimes be reached directly, which is where this overlaps with [hardening that works with your host rather than against it](/wordpress-security/). There is no upside to keeping them. Delete, do not just deactivate.

`wp plugin list --status=inactive --fields=name,version`

**Bucket two: duplicated function.** Two caching plugins. An SEO plugin plus a separate schema plugin plus a separate sitemap plugin. Two form plugins because someone tried a new one and never removed the old. Duplication here is worse than weight, because two plugins writing the same output can produce genuinely broken results, such as two conflicting canonical tags.

**Bucket three: a plugin doing a job that is ten lines of code.** Disabling emojis, adding a script to the footer, changing the login logo, adding a class to the body tag. Each of these carries an update surface, an options row and a maintenance obligation forever. Moving them into a small site-specific plugin of your own is usually correct, and gives you one thing to maintain instead of six.

**Bucket four: abandoned.** The signal to check is the WordPress.org listing: last updated date, tested-up-to version, and whether the plugin has been closed. Anything untouched for two years on a site that matters is a decision waiting to be forced by a PHP upgrade, which is exactly the trap described in [picking a PHP and MySQL pairing](/wordpress-php-version/).

**Bucket five: heavy but load-bearing.** Your page builder, your shop, your membership plugin. These are expensive and you are keeping them. The work here is configuration rather than removal: turning off the modules you do not use, and stopping asset loading on pages that do not need it, which is one of [the changes that measurably moved page load on the sites we run](/wordpress-speed-optimization/).

Five buckets, and what happens to each

Five buckets, and what happens to each

Inactive
still on disk, still needs patching

Duplicated function
two caching plugins, three schema sources

A job that is ten lines of code
disabling emojis, moving a script

Abandoned
last updated date, tested-up-to version

Heavy but load-bearing
the page builder, the shop, the membership plugin

Sorting comes after measuring, not before. Four of the five buckets have an obvious action, and the fifth is the only place judgement is needed.

## Removal without breakage: the order that matters

The dangerous part of removing a plugin is not deactivation. It is content that depends on it.

**Step one: find the content that references it.** Shortcodes are the common case. Before removing anything that provides one, search the posts table for the tag:

`wp db query "SELECT ID, post_title, post_status FROM $(wp db prefix)posts \
WHERE post_content LIKE '%[your_shortcode%' AND post_status IN ('publish','draft');"`

A shortcode whose plugin is gone does not error. It renders as literal text on the page, in front of readers, indefinitely. That is the most common way a cleanup becomes visible to the public.

**Step two: check for custom post types and taxonomies.** If the plugin registers a post type, removing it does not delete the content. The rows stay in `wp_posts` and become unreachable, with no admin screen and no front-end URL. Count them first:

`wp post list --post_type=that_plugins_type --format=count`

If the count is not zero, you need a migration plan before removal, not after.

**Step three: check blocks.** A block from a removed plugin leaves an invalid-block warning in the editor and, depending on the block, either its saved markup or nothing at all on the front end. Search `post_content` for the block comment:

`wp db query "SELECT COUNT(*) FROM $(wp db prefix)posts WHERE post_content LIKE '%wp:pluginslug/%';"`

**Step four: remove one plugin at a time, on staging, and look at the site.** Bulk deactivation tells you that something broke without telling you what caused it. One at a time is slower and it is the only method that produces an answer. This is exactly the work staging exists for, and the conditions that make staging trustworthy are in [WordPress staging done properly](/wordpress-staging/).

**Step five: uninstall properly, then check what it left behind.** Deleting through the admin triggers the plugin's own uninstall routine, which is your best chance at clean removal. Deleting the folder over SFTP skips that entirely and guarantees orphans.

`wp option list --search='pluginprefix_*' --fields=option_name,autoload
wp db query "SHOW TABLES LIKE '%pluginprefix%';"`

Leave orphan tables alone until you are certain the plugin is gone for good, then drop them deliberately. What is safe to prune and what is not is covered in [database maintenance](/wordpress-database-maintenance/).

## The all-in-one trap

The obvious response to plugin sprawl is to replace eight plugins with one suite that does all eight things. Sometimes that is right. Often it trades a spread of small risks for one large one.

The tradeoff, honestly stated: eight plugins means eight update streams and eight chances of an incompatibility, but any one of them can be swapped out in an afternoon. One suite means a single update stream and a single vendor, and switching away later means unpicking everything at once, usually including data stored in the vendor's own tables.

The question that decides it is exit cost. If leaving the suite in two years means a week of work and content rewriting, the sprawl was cheaper.

The same reasoning applies when you add rather than remove. AI crawler handling tends to arrive as three separate plugins, an llms.txt generator, a schema addon and something serving plain text copies of posts, which is the duplication bucket two warns about. [RankReady](https://wordpress.org/plugins/rankready-ai-llm-seo/) is the WordPress AI SEO plugin we use to hold all three jobs in one place, version 1.3.1, tested to WordPress 7.1, with about 300 active installs on WordPress.org. It runs alongside Rank Math, Yoast, AIOSEO or SEOPress without conflicting with them, sets up in about five minutes, and what it affects is crawlability rather than any ranking.

## What not to remove in a cleanup

Three things people cut for weight and then regret.

Your backup mechanism. Weight is irrelevant next to what it protects, and cleanup is precisely when you need it.

A caching layer that is currently working. Speed cleanups have a habit of removing the thing responsible for the speed.

Anything you cannot immediately explain. "Nobody knows what this does" is a reason to investigate, not a reason to delete on a Friday. On a site with any history, an unexplained plugin is occasionally holding up a redirect map or a legacy integration that nobody documented.

## Where Host My Blog fits

The method above is the entire method. Query Monitor is free, WP-CLI is free, and a careful afternoon on staging will get most sites through it.

Host My Blog does this as a scheduled review on the blogs we look after, folded into [the itemised hours of a maintenance month](/wordpress-maintenance-service/), because plugin sprawl is a slow accumulation and the natural moment to fix it never arrives on its own. If you have the afternoon and a staging site, do it yourself and keep the money.

One thing worth checking today, whatever you decide about the rest: how many deactivated plugins are still sitting in your `wp-content/plugins` directory right now?