Skip to main content
Drupal is a registered trademark of Dries Buytaert
Release: Drupal 12.0.0-beta1 — First beta version released for Drupal core (12.0.0-beta1). Release: External Authentication 2.0.14 — Minor update available for module externalauth (2.0.14). Release: Block Class 3.1.0 — Minor update available for module block_class (3.1.0). Release: Video Embed Field 3.1.1 — Minor update available for module video_embed_field (3.1.1). Release: Memcache API and Integration 8.x-2.9 — Minor update available for module memcache (8.x-2.9). Release: External Authentication 2.1.0-beta1 — First beta version released for module externalauth (2.1.0-beta1). Release: Drupal CMS Helper 2.2.2 — Minor update available for module drupal_cms_helper (2.2.2). Release: View Mode Switch Field 3.0.1 — Minor update available for module view_mode_switch (3.0.1). Usage Milestone: MathJax: LaTeX for Drupal — Module mathjax crossed 1,000 active installs. Module Revived: Audio Embed Field 11.1.2 — Module audio_embed_field updated after 8 months of inactivity (11.1.2).

Drupal Cleanup is a module designed to find and remove leftover data in your Drupal site that accumulates over time. It safely cleans up orphaned search index entries, moderation states, abandoned batch jobs, custom table rows, and old queue items for deleted entities. It also offers an option to clear out old temporary files from specified folders and includes a dry-run feature to preview changes before they are made.

In Testing

Drupal Cleanup finds and removes the leftover data a Drupal site builds up over time: search index rows, moderation states, queue items and custom table rows for content that no longer exists, plus abandoned batch jobs that core never purges.

Core cleans up after itself when content is deleted normally. But real sites also delete content in ways that skip the entity API: migrations, direct SQL, a bulk delete that dies halfway, or old code from before core handled it. What gets left behind never goes away. It bloats tables, slows queries and backups, and can surface dead results. This module finds those rows safely and removes them on a schedule, with a dry run so you can see what it would do first.

Features

  • Search index orphans: removes Core Search index entries for content that no longer exists, using core's own search.index service rather than raw SQL.
  • Content Moderation orphans: removes moderation states (and all their revisions) whose content is gone, for every moderated entity type, not just nodes.
  • Stale batches: purges abandoned rows from the batch table, plus the leftover drupal_batch:* queues they leave behind. Core has a cleanup method for this, but nothing calls it, so on long-running sites the table only ever grows.
  • Custom table orphans: any module can declare its own tables that store entity IDs in a small YAML file, and Drupal Cleanup keeps them tidy. No PHP needed, and no hard dependency: without this module the file is simply ignored.
  • Queue items for deleted entities: removes queued jobs whose target entity is gone, before a worker trips over them. Items a worker has already claimed are never touched.
  • Old working files: clears out scratch folders that imports and conversions leave on disk, by age, but only in folders a module has explicitly declared. Paths outside the site are refused, symlinks are never followed, and a folder that's still being written to is never touched. Modules can mark specific folders as protected.
  • Clean up the moment content is deleted: declared custom-table rows are removed as soon as their entity is deleted, batched into a few queries at the end of the request, so even bulk deletes stay fast. A cleanup failure is logged and never blocks the delete; the scheduled sweep catches anything missed.
  • Safe by design: a row is only removed when the entity it points at really doesn't exist. Nothing is ever deleted by ID range or date guesswork. Each task works in bounded chunks, and a task with bad configuration reports "misconfigured" and does nothing instead of failing.
  • Dry run everywhere: see exactly how many rows each task would remove before anything is deleted.
  • Extensible: every cleanup is a CleanupTask plugin, so modules can ship their own.

Post-installation

  1. Go to Configuration » System » Cleanup (/admin/config/system/cleanup).
  2. Turn on the tasks you want, and set how often the cron sweep runs (default: every 6 hours) and how many rows a task may remove per run.
  3. Before the first real run, check what would be removed:
    drush cleanup:list
    drush cleanup:run --dry-run
  4. Run it by hand with drush cleanup:run (optionally --task=<id>), or leave it to cron.

Tasks only appear when they apply: the search task needs the Search module, and the moderation task needs Content Moderation.

Declaring your module's tables, queues and folders

Add a MODULE.drupal_cleanup.yml file to your module:

mymodule_log:
  label: 'My module log rows'
  table: mymodule_log
  key: id
  references:
    - { column: nid, entity_type: node }
  match: any          # orphan if ANY reference is gone (or: all)

queues:
  mymodule_process:
    label: 'My module processing queue'
    entity_type: node
    data: scalar      # the item is the ID itself
    # or: data: { key: nid }   for array/object items

files:
  mymodule_tmp:
    label: 'My module scratch folders'
    path: 'public://mymodule/tmp'
    max_age: 604800   # 7 days (minimum 1 day)

A NULL reference never counts as an orphan. Queue cleanup works with core's database queue; queues on other backends are reported as unsupported and left alone. Only the folders listed under files: are ever touched, and each direct child is judged by the newest file anywhere inside it. To keep specific folders, implement hook_drupal_cleanup_protected_paths_alter(array &$paths, string $task_id).

Additional requirements

Drupal 10.3 or later, or Drupal 11. No other modules or libraries. Drush 12+ for the command-line tools (optional).

Recommended modules/libraries

None required. The search and moderation tasks turn on automatically when core's Search and Content Moderation modules are enabled.

Supporting this module

Bug reports, feature requests and patches are welcome in the issue queue. If your module keeps entity IDs in its own tables or queues, a MODULE.drupal_cleanup.yml file is a small, dependency-free way to keep sites that use it clean.

Built by Easy Life Agents @ Global Web Methods

More Modules

Module Cleanup -- Lists uninstalled or deleted modules with leftover transient data and allows the admin to delete any leftover data. A fix for Module 'module_name' has an entry in the system.schema key/value storage.
A fix for The 'module_name' entity type does not exist error. The module with the entity must be installed.

Recipe Filter -- Recipe Filter adds a "Recipe Type" sidebar menu to the Project Browser Recipes page — the same way core's Module Filter functionality builds a sidebar for the Modules page. Instead of hunting through a flat list or a collapsed drop-down, you get an always-visible menu of recipe types, each with a live count, so you can jump straight to the recipes you're looking for.

Permissions Table -- Fixes the permissions table by making the table header fixed to the top and horizontal scrollbar fixed to the bottom of the the permissions table.

Originally built for DocSyntra by EasyLifeAgents via Claude Code.

Depends on

Dependencies of the latest stable release

No dependencies recorded for this project.

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
1
Tracked since
Sep 2026
Latest release
5 hours ago
Releases (12 mo)
1 ▲ from 0
Maintenance
Active

Releases

Version Type Core Release date
1.0.x-dev Dev 10–11 Sep 30, 2026