Deleting code feels risky because the absence of a thing is harder to inspect than its presence. Yet every unused path adds another possibility a future change has to preserve.
Signs of a removable path
Look for:
- a feature flag that has been permanently enabled;
- a fallback for a system that no longer exists;
- a helper with one caller and no meaningful abstraction;
- a comment describing behavior that the code no longer has;
- a test for an intentionally removed requirement.
Delete in small steps
1. Confirm the old path has no active callers.
2. Remove the entry point.
3. Remove tests and helpers that only served it.
4. Build and inspect the diff.
5. Record the reason in the change description.
| Question | Why it matters |
|---|---|
| Is it reachable? | Dead code may still be called indirectly |
| Is it documented? | Users may depend on an undocumented path |
| Is it tested? | Tests can reveal hidden contracts |
| Is there a migration? | Removal may need a transition period |
Deletion is a user-facing improvement
Less code means fewer branches, fewer assumptions, and fewer places for a security fix to be missed. A smaller system is easier to explain and easier to trust.
Maintenance is not only adding support for the future. It is removing support for the past when the past is no longer part of the product.