Short answer for site owners: when you deactivate a WordPress plugin, it stops running but keeps its settings and data, and its files stay on your server. When you delete it, WordPress removes the files, and the plugin’s own cleanup code (if it has any) runs. Many plugins have no cleanup code, so their settings and database tables stay behind after deletion. A deactivated plugin does not slow your site by running code, but leftover data can still add weight, so a clean uninstall matters.

Short answer for developers: put cleanup in uninstall.php (or register_uninstall_hook()), guard it with WP_UNINSTALL_PLUGIN, make deleting user data an opt-in setting, and loop over sites on multisite. A working example is below.

What happens when you deactivate a WordPress plugin?

Deactivating a plugin tells WordPress to stop loading its code. Nothing else changes by default.

  • The plugin’s PHP no longer runs, so it adds no hooks, scripts or queries.
  • Its settings stay in the database. If you reactivate it, everything is as you left it.
  • Its custom tables, post meta, user meta and scheduled tasks are untouched unless the plugin cleans them on deactivation.
  • Its files stay in wp-content/plugins/.

Plugins can run code at this moment with register_deactivation_hook(). The right use is light housekeeping: clear scheduled events and flush rewrite rules. Deleting user data on deactivation is a mistake, because deactivating is something people do to troubleshoot, and it should be reversible.

What is the difference between deactivating and deleting a plugin?

DeactivateDelete
Plugin code runsNoNo
Files on serverStayRemoved
Settings in databaseStayRemoved only if the plugin has cleanup code
Custom tablesStayRemoved only if the plugin has cleanup code
Can you switch back on?Yes, instantlyOnly after reinstalling, and data may be gone or still there
Security exposureFiles still on diskFiles gone

The security row surprises many owners. A deactivated plugin is not loaded by WordPress, but its files can still sit in a public folder. If a file in that plugin has a known vulnerability, it can sometimes be reached directly by URL. That is why you should delete plugins you do not plan to use, not leave them deactivated. Our piece on the plugin security problem nobody talks about goes deeper.

Do deactivated plugins slow down WordPress?

No, not by running code. A deactivated plugin is not loaded, so it cannot run queries or add scripts to your pages. That part of the old advice is a myth.

What can slow a site is the data a plugin leaves behind, mainly in one place: autoloaded options. WordPress loads every option marked autoload = yes on every request, whether or not the plugin that created it is still active. A removed plugin that left several large autoloaded options will keep adding to every page load. Leftover custom tables and post meta mostly cost disk space and backup time, not page speed, though large tables on a busy site can still matter for exports and backups.

So the honest answer is: deactivated plugins do not slow your site down, but uncleaned plugins can. If you want to check your own site, look at the total size of autoloaded options with a database tool or a health check from your host or developer. If you use a maintenance plan, ask whether it covers this. Our guide to WordPress maintenance services explains what a regular check should include.

Does deleting a plugin remove its data?

Only if the plugin was written to do that. WordPress runs the plugin’s uninstall code when you delete it from the Plugins screen. If the plugin has no such code, WordPress deletes the files and stops there. Settings, tables, uploaded files and user meta remain.

This is why a plugin you tried once and removed can leave rows in your database years later. It is also why some developers are careful: for plugins that store orders, form entries or member content, an automatic wipe on delete could destroy data you wanted.

How do you clean up a plugin properly on uninstall?

WordPress gives developers two supported ways to run cleanup on delete.

  1. uninstall.php in the plugin’s root folder. WordPress runs this file when the plugin is deleted. This is the simplest option and the one the plugin handbook points to first.
  2. register_uninstall_hook( $file, $callback ) called from the main plugin file. WordPress stores the callback and runs it on delete. The callback must be a named function or static method, not a closure, and you should not use both methods in the same plugin.

Both run only when a plugin is deleted from the admin, never on deactivation. uninstall.php runs on its own, with the rest of your plugin not loaded, so it must not depend on your plugin’s classes or functions.

What does a correct uninstall.php look like?

This example removes data only if the site owner opted in, handles multisite, and cleans options, post meta, user meta, scheduled events and a custom table. Change the myplugin_ names to your own prefix.

query( "DROP TABLE IF EXISTS {$wpdb->prefix}myplugin_log" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
}

if ( is_multisite() ) {
	// WordPress runs this file once for the network. Visit every site.
	foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0 ) ) as $site_id ) {
		switch_to_blog( $site_id );
		myplugin_uninstall_site();
		restore_current_blog();
	}
} else {
	myplugin_uninstall_site();
}

Notes on the choices in that file:

  • The WP_UNINSTALL_PLUGIN check stops anyone from running the file by requesting its URL.
  • The opt-in setting protects against accidental data loss. The default is to keep data.
  • The multisite loop matters because WordPress calls the file once, and each site has its own options and tables. 'number' => 0 removes the default limit of 100 sites.
  • Prefix everything. Function names in this file share the global namespace, so use your plugin’s prefix.
  • Files and folders you wrote to uploads need their own removal code. Use WordPress file functions and delete only paths you created.

How does register_uninstall_hook work?

If you prefer to keep cleanup in the main plugin file, register a callback once, on every request where the plugin loads or when it activates:

A few rules apply. The callback must be a function name or a static class method, because WordPress saves it in the database and calls it later. It runs only on delete. uninstall.php is simpler to reason about, since it is a separate file that only runs on delete and does not load your plugin.

See the WordPress developer handbook for the official description: Uninstall Methods, and the register_uninstall_hook reference.

Why should data deletion be opt-in?

Because the cost of a mistake is lopsided. If cleanup is automatic and someone deletes the plugin by accident, or deletes it to reinstall a fresh copy, they lose orders, entries, member content or configuration with no way back. If cleanup is off by default and someone leaves data behind, the cost is some unused rows.

The pattern that works for most plugins:

  1. Add a clearly worded setting such as “Delete all plugin data when the plugin is deleted” in an Advanced tab.
  2. Default it to off for plugins that hold user-generated content.
  3. Explain what is removed and that it cannot be undone.
  4. Optionally add a manual “Delete plugin data now” button for owners who want to clean up without removing the plugin.
  5. Document what the plugin stores.

WooCommerce takes a similar view. It keeps its data by default, and a site owner can choose full removal by defining the WC_REMOVE_ALL_DATA constant in wp-config.php before deleting the plugin. That puts the choice in the hands of the person who understands the risk.

How do you find leftover autoloaded options from old plugins?

If you have shell access, WP-CLI can list the biggest autoloaded options on your site. Sorted by size, the top entries often show up as names that start with a plugin prefix you no longer use.

wp option list --autoload=on --fields=option_name,size_bytes --format=csv | sort -t, -k2 -nr | head -20

Do not delete a row just because the name looks unfamiliar. Search the name first, work out which plugin owns it, and take a database backup before removing anything. Some options belong to plugins you still use, and themes and WordPress itself store large options too. If you are not comfortable with this, ask your host or developer to review it. A small number of large options is normal, and the goal is only to catch obvious leftovers from plugins that are long gone.

Developers can prevent the problem from the other side. When you save an option that is read only on one admin screen or one feature, pass false as the autoload argument to add_option() or update_option(), so it is not loaded on every request. That keeps your plugin light while it is active, and it limits the damage if the plugin is ever removed without cleanup.

Do our own plugins follow this pattern?

Some of ours do, and we checked the code to say so. WB Listora, Eventonomy and WPMediaVerse each ship a “delete data on uninstall” setting that is off by default, and each cleans up only when the site owner turns it on. WB Listora also loops over every site on multisite and honours each site’s own choice. We do not claim every plugin we have ever shipped works this way, and older plugins in our catalogue may clean up differently, so check a plugin’s documentation before you delete it.

How can site owners check a plugin before installing or deleting it?

  • Read the FAQ and settings page. Look for words like “delete data on uninstall” or “remove data”.
  • Back up first. Take a full backup before deleting any plugin, even one that claims to clean up. A tool like UpdraftPlus can automate this.
  • Use a staging copy to delete the plugin and see what remains.
  • Scan for leftovers after deleting. Tools such as WP-Optimize and Advanced Database Cleaner can find orphaned tables and options. Review each item before removing it, because a wrong delete is permanent.
  • Ask the developer. If a plugin leaves data behind with no way to remove it, say so in the support forum.

What is a good cleanup checklist for plugin developers?

  • Add uninstall.php or register_uninstall_hook(), not both.
  • Check WP_UNINSTALL_PLUGIN first.
  • Make deleting user-generated data opt-in.
  • Remove options, post meta, user meta, terms and custom tables you created.
  • Clear scheduled events and transients.
  • Handle multisite by looping over sites.
  • Use deactivation only for light housekeeping, such as clearing cron events and flushing rewrite rules.
  • Avoid autoloading large options. Set autoload to false for data that is not needed on every request.
  • Test the full cycle: activate, use, deactivate, reactivate, delete, then inspect the database.

Frequently asked questions

Is it safe to deactivate a plugin?

Yes. Deactivating stops the plugin without removing data, and you can turn it on again. It is the safe first step when you are troubleshooting. Features that depended on the plugin will stop working until it is back.

Will deleting a plugin delete my content?

Not content in your posts and pages, but it can remove data stored by the plugin itself, such as form entries or custom tables, if the plugin’s uninstall code removes them. Back up first and read the plugin’s documentation.

Why is there still data in my database after I deleted a plugin?

The plugin had no cleanup code, or its cleanup is opt-in and was switched off. This is common and not always a fault. A cleanup tool can help, but review before you delete anything.

What is the difference between uninstall.php and register_uninstall_hook?

Both run when the plugin is deleted. uninstall.php is a separate file in the plugin root. register_uninstall_hook() registers a callback from the main plugin file. Use one, and prefer uninstall.php for clarity.

Does uninstall code run when I deactivate a plugin?

No. It runs only on delete. Deactivation has its own hook, register_deactivation_hook(), which should not remove user data.

How many deactivated plugins is too many?

There is no performance limit, since they do not run. But each one is code on your server that needs updates and may hold vulnerabilities. Delete what you do not use.