Every org has a graveyard: Flows named OLD_DO_NOT_USE, fields no layout shows, permission sets nobody holds. And every cleanup initiative stalls on the same sentence: “the last time someone deleted something unused, quoting broke for two days.”
The epistemic gap
“Unused” is a claim about references; “safe to delete” is a claim about the world. Metadata dependency data records what references what — but scheduled Apex, invocable actions and direct page placements can show zero incoming edges while being entry points; and reports, list views, dashboards and API consumers are not in the dependency data at all. A component with no recorded references is a candidate, never a verdict.
A discipline that holds up
Rank candidates by evidence (zero recorded references, inactive-only referencers, no similarity twins) rather than by name. Check the invisible surfaces — reports, list views, integrations — the one step no scan does for you. Retire reversibly: deactivate before delete, export the change as a bundle, keep a rollback. And prove it: re-scan, confirm the graph changed as planned, and let the shrinking history make the next deletion easier to approve.
Horus Eye’s cleanup signals are built on that humility — the field-retirement rule skips any field with even one reference whose status it cannot read, because a claim the data cannot support is worse than a missed candidate.
Where references hide
The reason “nothing references this” is a hypothesis rather than a fact: Salesforce references live in places no sidebar shows. Email templates hold merge fields that resolve at send time. Report and list-view filters name fields without creating dependencies the UI surfaces. Scheduled jobs and queueable Apex can construct names dynamically, so the reference exists only as a string until the night it runs. Integration users select fields through the API with no metadata trail at all. A field can sit “unused” for a year and still be load-bearing on the first of the month.
A safe retirement sequence
Retire in stages that each produce evidence. First, inventory what you can see: dependency checks, report filters, template merge fields, and the API usage you can sample from logs. Second, make the candidate inert without deleting it — remove it from layouts, strip it from permission sets so reads fail loudly rather than silently. Third, rename with a DEPRECATED- prefix and wait a full business cycle, including quarter-end if finance touches it. Only then delete — in a sandbox first, with the deployment validated against real automation. Every step is reversible except the last, which is exactly why the last step comes last.
The bottom line
“Unused” is a claim about the past; deletion is a bet about the future. The staged sequence — inventory, inert, deprecated, deleted — converts that bet into a series of cheap, reversible experiments, each of which either surfaces the hidden reference or strengthens the case. Cleanup done this way is slower per field and far faster per org, because nothing has to be restored at quarter-end with an auditor watching.

