Salesforce destructive changes let you remove fields, objects, and other metadata from an org through a deployment instead of clicking delete in Setup. They sound simple until you realize deletion in Salesforce is never isolated. A field you want gone might be referenced in a flow, a validation rule, a report type, or an Apex class that nobody has opened in two years. Get the order or the dependency chain wrong, and your clean-up deployment turns into an outage.
Change Sets handle this badly, which is one reason teams move to Metadata API-based tooling the moment they need to delete anything beyond a sandbox test field. Change Sets can add and modify metadata, but they were never built to express removal cleanly across environments. That gap is where destructive changes manifests come in, and where most admins first discover how unforgiving Salesforce is about cleanup.
What destructive changes actually are
A destructive changes deployment uses two files, destructiveChangesPre.xml and destructiveChangesPost.xml, paired with a package.xml. Pre-deletion removes metadata before new components deploy. Post-deletion removes it after. The distinction matters more than it looks: deleting a field before a flow that still references it will fail outright, while deleting it after lets the flow deploy clean, then strips the old field once nothing points to it.
Most teams default to post-deletion because it is more forgiving, but that forgiveness has a cost. Post-deletion runs last, which means if anything earlier in the deployment fails, your deletions never happen and you are left with half-finished metadata sitting in production. Pre-deletion is riskier to write but gives you a cleaner failure mode: if the deletion itself is wrong, nothing else in the deploy proceeds either.
The order problem nobody plans for
Deletion order inside Salesforce follows dependency rules, not the order you list items in your manifest. You cannot delete a custom field that a validation rule still references, even if both are listed in the same destructiveChangesPost.xml. The platform checks references at deploy time and rejects the whole batch if anything still points to the component you are trying to remove.
This is why "just delete it and see what breaks" is such an expensive habit. A field used in one validation rule is easy to spot. A field used in a formula field, three report types, a Visualforce page nobody remembers building, and an Apex trigger with no inline comments is not. Salesforce will tell you the deploy failed. It will not hand you the full dependency tree in one readable list.
Why metadata deletion breaks things silently
The failures that actually hurt are not the ones that block your deployment. Those are annoying but visible. The dangerous ones are the deletions that succeed technically but break a downstream process nobody tested.
Picklist values removed through a destructive change can silently invalidate records that still carry the old value, depending on how your automation handles unmatched picklist states. Custom fields deleted from a managed package's dependent configuration can break integrations that reference the field by API name in external systems Salesforce has no visibility into. A Lightning page component tied to a field you just deleted will often just show blank space in production, with no error log pointing back to the deployment that caused it.
| Deletion target | Common hidden dependency | Failure mode if missed |
|---|---|---|
| Custom field | Formula fields, flows, report types | Deploy fails or reports silently drop data |
| Picklist value | Validation rules, record type picklist assignments | Records with old value behave unpredictably |
| Custom object | Lookup relationships, Apex SOQL, page layouts | Apex throws runtime errors post-deploy |
| Validation rule | Test class assertions expecting the rule to fire | Test coverage drops below threshold |
| Flow | Process Builder references, Apex-invoked actions | Automation stops triggering with no error surfaced |
Every row in that table has shown up in a real production incident at some point, and the common thread is visibility. Salesforce does not warn you about every dependency before you delete something. It only stops you when the reference is one the deploy engine happens to check.
Common patterns that trip up even experienced admins
Deleting a field that feeds a formula field elsewhere in the same object is the classic beginner mistake, and it gets caught immediately because the formula field deploy fails loudly. The harder pattern is deleting a field referenced only in Apex test data setup. The test still compiles. It still runs. It just quietly stops testing the scenario it was written for, and nobody notices until an unrelated bug slips past coverage that used to catch it.
Another pattern worth flagging: record types tied to a picklist value you are removing. If a record type restricts available values and you delete one that is still assigned as the default for that record type, Salesforce will often let the deletion through in sandbox but behave differently in production depending on existing record data. That inconsistency between sandbox and production is exactly why destructive changes deserve more testing rigor than a standard field addition.
Managed package dependencies deserve a separate mention. If a package references a standard or custom field you are deleting, even indirectly through a trigger the package ships with, your destructive change can fail against a component you do not own and cannot inspect the source of. That is not a hypothetical. It is the single most common reason destructive deployments stall in orgs running CPQ, Field Service, or any sizable AppExchange footprint.
A safer deletion workflow
The admins who handle this well follow a consistent sequence instead of improvising per deletion. It is not glamorous work, but it is the difference between a clean deploy and a weekend incident call.
- Run a full dependency search in Setup before writing any destructiveChanges.xml, using both the Field Usage view and a metadata dependency API query rather than relying on memory.
- Deploy the destructive change to a full or partial sandbox first, and actually exercise the affected business processes rather than checking only for deploy success.
- Prefer post-deletion over pre-deletion unless you have a specific reason the field must be gone before new metadata lands, since post-deletion gives new components a chance to deploy even if the delete step needs a retry.
- Separate destructive deployments from feature deployments. Bundling a deletion with unrelated new functionality makes rollback far harder if either half fails.
- Keep a rollback manifest ready that can recreate the deleted component's definition, even if the data behind it cannot be restored from a backup.
That last point gets skipped constantly, and it is the one that matters most once something goes wrong. Recreating a field's metadata definition takes minutes. Recovering the data that lived in it, if you deleted the field without an export first, often does not happen at all.
Where automation actually changes the outcome
Manual destructive changes management does not scale past a small team working in a single sandbox. The moment you have multiple developers, multiple sandboxes, and a release calendar, tracking which deletions are safe against which branch of metadata becomes a spreadsheet exercise that falls apart within a quarter.
This is the exact problem DeployEzee was built to handle. It resolves metadata dependencies before a deployment runs, flags components still referencing something scheduled for deletion, and sequences pre- and post-destructive changes automatically instead of leaving the order to guesswork. Instead of an admin manually cross-checking Field Usage pages against a manifest, the dependency graph gets built once and reused across every environment in the pipeline.
The practical result is fewer deployments that fail on a reference nobody caught, and fewer post-deploy surprises where something deletes cleanly but breaks a process three steps removed. Destructive changes will always carry more risk than additive ones. There is no tool that makes deletion inherently safe. What good tooling does is make the risk visible before it becomes an incident, which is the entire point of automating the part of deployment work that humans are bad at doing consistently.
Frequently Asked Questions
What is the difference between destructiveChangesPre.xml and destructiveChangesPost.xml?
destructiveChangesPre.xml deletes metadata before the rest of the deployment package is deployed, which is useful when old components would conflict with new ones. destructiveChangesPost.xml deletes metadata after the rest of the package deploys successfully, which is safer in most cases because it does not block the deployment of new components if the deletion itself has an issue. Most teams default to post-deletion unless there is a specific conflict that requires removing something first.
Can Change Sets handle destructive changes in Salesforce?
Change Sets can include some deletions, but they are far less reliable than a proper destructiveChanges.xml manifest deployed through Metadata API. Change Sets were primarily designed for adding and modifying metadata, not for the dependency-aware deletion that removing fields, objects, or picklist values usually requires. Most teams running regular cleanup deployments move to Metadata API tooling specifically because of this limitation.
Why does Salesforce block a destructive change deployment even when the field looks unused?
Salesforce checks metadata references at deploy time, and a field can be referenced in places that are not obvious from the page layout, including formula fields, report types, flows, and Apex test classes. If any dependent component still points to the field, the deletion fails even though the field appears unused in day-to-day usage. A thorough dependency search before building the manifest catches most of these references ahead of time.
What happens to data when you delete a custom field through a destructive change?
The field and its data move to a recoverable state for a limited window, generally around 15 days, after which it is permanently purged along with the stored values. Recreating the field's metadata definition afterward is quick, but the original data itself is not restored unless it was exported beforehand. Any deletion plan should include a data export step before the destructive change deploys, especially in production.
How do automated deployment tools reduce risk in destructive changes?
Automated deployment tools build a dependency graph of metadata before a deployment runs, which flags components still referencing something scheduled for deletion instead of letting the failure surface mid-deploy. They also help sequence pre- and post-destructive changes correctly so new metadata and deletions do not conflict. This moves dependency checking from a manual, error-prone process to a consistent automated step applied the same way across every environment.