Every line of code is a liability. It can break. It needs maintenance. It confuses new developers. The best code is code that doesn't exist.

Why We Don't Delete

Sunk cost fallacy. "I spent three days writing this."

Fear. "What if we need it later?"

Uncertainty. "I'm not sure if anything uses this."

Ownership. "Someone might be upset if I delete their code."

None of these are good reasons to keep code around.

Signs Code Should Go

It's commented out:

# def old_implementation():
#     # This used to do something
#     pass

Delete it. Git remembers.

It's behind a feature flag that's always off:

if ENABLE_LEGACY_FEATURE:  # Never true
    do_legacy_thing()

Delete it. The flag too.

Nothing calls it:

def unused_helper():
    """Written for a feature that was never shipped."""
    pass

Delete it. Your IDE can find unused functions.

It's a "just in case" abstraction:

class AbstractStrategyFactoryBuilder:
    """We might need this flexibility someday."""
    pass

Delete it. YAGNI.

How to Find Dead Code

Static analysis:

# Python
vulture src/
 
# JavaScript  
npx unimported

Coverage reports: Code that's never executed in tests might be dead.

Search for references:

grep -r "function_name" src/

Feature flags audit: List all flags. Delete code behind permanently-off flags.

The Deletion Process

  1. Identify the code to delete
  2. Verify nothing uses it (grep, IDE, tests)
  3. Delete in a focused commit
  4. Test that nothing breaks
  5. Deploy and monitor

Keep deletion commits separate from feature work. If something breaks, reverting is easy.

Overcoming Fear

Git is your safety net. Deleted code lives forever in history. You can always get it back:

git log --all --full-history -- path/to/deleted/file.py
git checkout <commit>^ -- path/to/deleted/file.py

Tests catch breaks. If your tests pass, the deletion is probably safe. If tests don't cover the code, maybe add them first—or accept the risk.

Production monitoring. If deleted code was actually needed, errors will tell you. Have good monitoring.

What to Delete First

Easy wins:

  • Commented-out code
  • Unused imports
  • Dead feature flag branches
  • Old migration files (after running)
  • Deprecated endpoints (after removal period)

Medium effort:

  • Unused utility functions
  • Old API versions
  • Legacy database columns
  • Redundant abstractions

Requires planning:

  • Entire unused services
  • Old authentication systems
  • Database tables

Deletion as a Practice

Schedule regular cleanup:

  • Weekly: commented code, unused imports
  • Monthly: dead functions, unused files
  • Quarterly: unused features, old APIs

Make it part of the workflow. Don't let cruft accumulate.

The Payoff

Less code means:

  • Faster builds
  • Easier onboarding
  • Fewer bugs
  • Lower cognitive load
  • Simpler refactoring

Every line you delete makes the codebase better.

My Rule

If I'm not sure whether code is used, I delete it and see what breaks.

Sounds reckless. But with good tests and monitoring, the risk is low and the reward is high. Dead code is noise. Noise slows everyone down.

Delete with confidence. Git has your back.

React to this post: