Disabling Unused Modules to Improve Performancefor Drupal 11 , 10 , 9 , and 8

Last updated :  

Every enabled module adds real, measurable overhead — its own hook implementations run on every relevant request, its own routes get registered and checked, its own services get built into the container, whether or not you actually use most of its functionality. A module you installed to evaluate six months ago and never removed is quietly taxing every single page load, even if nothing on your site visibly uses it anymore.

What you'll learn in this lesson

  • Why "disabled but installed" isn't actually free in Drupal 8+
  • How to find modules that are enabled but genuinely unused
  • The real difference between uninstalling and just disabling

Why enabled-but-unused still costs something

Unlike Drupal 7, modern Drupal has no separate "disabled" state — a module is either installed (enabled) or fully uninstalled. Every installed module's .services.yml entries get compiled into the container, its hook implementations get included in hook_module_implements_alter()'s discovery, and its routes get registered — all real, if individually small, costs that add up across dozens of modules.

Finding genuinely unused modules

# List everything currently enabled.
drush pm:list --status=enabled

# Cross-reference against what's actually referenced in exported config —
# a real signal a module's functionality is actually wired into the site.
grep -rl "module_name" config/sync/ | wc -l
Don't trust "seems unused" alone. A module with zero visible admin-UI footprint can still be silently load-bearing — providing a field type another module's config depends on, or a permission referenced by a role nobody's edited recently. Check drush pm:list's dependency information and search exported config for the module's machine name before removing anything from a production site.

Uninstalling, not just leaving disabled

# This actually removes the module's overhead — its schema, its config,
# its container-compiled services, all of it.
drush pm:uninstall module_name

Since there's no "disabled" state to fall back into, "removing" a module's overhead means uninstalling it properly — which also cleanly removes its database tables and configuration, rather than leaving orphaned schema behind that a future re-enable would collide with.

Quick check: you find a module enabled with no visible admin pages or blocks anyone uses. Is it automatically safe to uninstall? If you said no — it might still provide a field type, a service another module depends on, or a permission a role references — you've understood why "seems unused" needs verification, not just a visual check.

Key takeaways

  • Modern Drupal has no free "disabled" state — every installed module carries real, if small, per-request overhead.
  • drush pm:list plus grepping exported config for a module's machine name is a real way to check whether it's actually load-bearing.
  • Uninstall (not just disable, since that state doesn't exist) to actually remove a module's overhead, including its schema and config.
  • Always verify dependencies before removing anything from production — a quiet module can still be structurally important.

Coming up next

Removing unused modules trims overhead you don't need at all. Next, we look at the modules you do keep — specifically, how to keep their hook implementations from adding unnecessary cost of their own.