Bulk Delete is the only governed mechanism for mass deletion in Dataverse. It runs asynchronously, respects security, fires plugins (or skips them if you ask), and writes its own audit trail. Most teams treat it as an emergency tool. Treat it as a regular maintenance one.
The recurrence pattern that works
Schedule a monthly recurring Bulk Delete per high-churn table. The job runs unattended, emails the owner on completion, and keeps the table from accumulating cruft. Recurring jobs are configured at creation time:
Settings -> Data Management -> Bulk Record Deletion -> New
-> Define query -> Schedule: monthly -> Notify on completion
Skip plugins when you mean it
By default, Bulk Delete fires Delete plugins on every row. For a 200,000-row purge, this is hours of plugin runtime. The IsBulkDelete flag is exposed in the plugin context if you want plugins to short-circuit themselves:
if (context.MessageName == "Delete") {
bool isBulk = context.SharedVariables.ContainsKey("BulkDelete");
if (isBulk) return;
}
For maintenance deletes that should bypass logic entirely, use the ExecuteMultiple approach with BypassCustomPluginExecution set on the request, which requires the executing user to have the bypass privilege.
Cascading rules apply
A delete cascades according to the relationship behavior. Deleting an Account with Cascade All will delete every Contact, Opportunity, and related row. Bulk Delete enforces this. Always preview your query for relationship breadth before running. The “Number of records that match” count does not include cascaded children.
Audit retention vs Bulk Delete
A common mistake: you set audit retention to 90 days, expect storage to drop, and it does not. The audit retention setting marks rows for deletion. Actual deletion happens via the system Bulk Delete job named Audit log retention. If that job is paused or failing, your retention setting is decorative. Verify the job is running monthly.
Recovery is impossible
Bulk Delete is final. There is no recycle bin. If you delete 50,000 rows and discover you should not have, the only recovery is restoring the environment to a backup, which is hours of downtime and loses every change since the backup. Always test the underlying query in Advanced Find first, then run Bulk Delete with a hard top limit on the first execution.
Performance reality
Bulk Delete throughput is roughly 2,000-5,000 rows per minute depending on table complexity and cascading. A 1M row purge is overnight. Schedule large jobs for off-hours and on environments where storage I/O is not contended.
What to do this week
List every active Bulk Delete job with its last run status. Any job in failure state is silently letting your storage grow. Fix or delete them.