All Things PM
AI & techEngineering

Your Codebase Has a Ghost Problem, and AI Just Made It Worse

A Wall Street firm lost $460 million in 45 minutes because of code nobody remembered was still there. Here is why every PM shipping with AI needs to care about the code that never gets deleted.

All Things PM·August 8, 2026·8 min read
A product manager holds a lantern in a dark server room full of ghostly disused code
A product manager holds a lantern in a dark server room full of ghostly disused code

The Bug Was Eight Years Old

On the morning of August 1, 2012, Knight Capital Group turned on new trading software and started losing about $10 million a minute. Within 45 minutes the firm had executed millions of erroneous orders across 397 million shares, taken a loss of more than $460 million, and become effectively insolvent overnight.

The cause was not some exotic new failure. It was old code that nobody had deleted.

Years earlier, Knight had built a feature called Power Peg for a manual order-routing function. In 2005, engineers moved the underlying tracking logic to an earlier point in the system, which made the original Power Peg code obsolete. Nobody removed it. It just sat in the router, unused, "safe" because nothing was supposed to call it anymore.

In July 2012, a technician deploying new code for a different feature updated seven of Knight's eight production servers. The eighth kept the old code path. When markets opened the next day, orders hit that stale server, woke up the dormant Power Peg logic, and it started buying and selling stock with no cap and no one watching. Knight was acquired by Getco a few months later.

This is dead code: any function, file, or code path that nothing in your live product actually calls. It gets written, it ships, and then it just sits there. Most of the time it is harmless clutter. Sometimes, like at Knight Capital, it is a loaded gun nobody remembered leaving in the drawer.

Why This Is Suddenly a PM Problem, Not Just an Engineering One

For most of software history, dead code accumulated slowly. A team would deprecate a feature, get busy, and leave the old implementation behind. It was a background tax, not a crisis.

AI coding assistants changed the math. When writing code is nearly free, teams produce far more of it, and the unused, duplicated, and half-finished parts pile up faster than anyone can track or remove them. GitClear, a code-analytics firm, studied this directly. It analyzed 211 million lines of code changes from 2020 to 2024 across a large sample of repositories and found that duplicated code blocks rose eightfold in 2024 alone. More strikingly, 2024 was the first year in GitClear's dataset where copy-pasted code outnumbered code that was moved or refactored from elsewhere.

Copy-pasted lines went from 8.3% of all changed code in 2020 to 12.3% in 2024, a 48% relative jump. Meanwhile "churn," code substantially rewritten or reverted within two weeks of being written, rose from 5.5% to 7.9%, a rough proxy for code landing without enough context or review, which is exactly the kind of code that tends to get abandoned rather than cleaned up.

If you are a PM greenlighting an AI coding tool rollout for your team, this is your problem too. You are the one setting velocity targets and celebrating shipped-feature counts. If "code produced" goes up without anyone tracking "code removed," you are quietly signing up for a codebase that gets harder to secure, harder to onboard into, and harder to trust with every sprint.

Extreme close-up of a photocopier churning out endless identical code sheets

AI coding tools make writing code nearly free. They do nothing to make deleting it easier, and that asymmetry is where the debt piles up.

Why You Cannot Just "Turn On a Detector" and Trust It

Here is the uncomfortable part: perfectly detecting all dead code is not just hard, it is mathematically impossible in the general case. This traces back to a result in computer science called Rice's theorem, related to the halting problem, which shows that no general algorithm can decide all non-trivial semantic properties of an arbitrary program, including "will this code ever run." Any dead-code detector is working from heuristics, not certainty.

That matters in practice because code can look unused and still be very much alive. A function might only be called through reflection, a config file, a dynamically built string, or a framework hook that never appears as a direct reference in the source. This is exactly the trap Knight Capital fell into in spirit: code that looked safely retired because nothing in the obvious call path touched it anymore.

The same product manager, flashlight in hand, lost in a maze of pipes and wires with one path glowing faintly in the shadow

Good tools are honest about this uncertainty instead of pretending it away. Vulture, a popular Python dead-code scanner, tags every finding with a confidence score rather than a flat yes-or-no verdict, so a team can triage "we are 90% sure this is dead" separately from "this might be dead, check before deleting." That is the right mental model for a PM to carry into planning: dead-code tooling produces leads to investigate, not an automatic delete button.

Static analysis itself is not new. Lint, one of the earliest widely used static-analysis tools, was written in 1978 by Stephen C. Johnson at Bell Labs to catch portability bugs while Unix was being ported to a new machine, and shipped publicly the following year. Checking for unreachable code was one of lint's original features. The idea is nearly as old as compiled languages themselves. What is new is the volume AI assistants are throwing at it.

What This Actually Costs a Product Team

A tiny product manager stands at the base of a colossal, teetering skyscraper built from mismatched code blocks

Dead and duplicated code is not just an aesthetic complaint from engineers who like tidy repositories. It has measurable downstream cost.

Research on cloned code blocks links duplication to roughly 15% to 50% more defects, because a bug fixed in one copy silently stays broken in every other copy nobody remembered existed. Every dead code path is also attack surface: code that can still execute, still has permissions, and is not being watched because everyone assumes it does not matter. It is also a tax on ramp-up time, since new engineers have to read through dead branches to figure out what is actually load-bearing, which slows down exactly the fast-shipping workflow AI tools were supposed to enable.

None of this shows up in a sprint velocity chart. It shows up months later as a mysterious production incident, a security audit finding, or a new hire who takes twice as long to ship their first feature because they could not tell which of three near-identical functions was the real one.

The Playbook: Ship a Guardrail, Not Just a Feature

The fix is not "ban AI coding tools." It is treating dead-code and duplication tracking as part of the definition of done for an AI-assisted workflow, the same way test coverage became part of the definition of done a decade ago.

Add a dead-code and duplication check to the build pipeline. For JavaScript and TypeScript teams, Knip has become the recommended tool, replacing older options like ts-prune, which is now in maintenance mode. For Python teams, Vulture does the same job with its confidence-scored output. Neither tool needs to block every merge; even a weekly report a PM can glance at is enough to start making the invisible visible.

Track dead-code and duplication counts next to shipping velocity, not instead of it. The goal is not to slow the team down. It is to make sure "we shipped 40 features this quarter" is reported alongside "and we deleted the equivalent of 6 features' worth of dead code," so leadership sees the full picture instead of only the growth number.

Reward code deleted, not just code added. Performance reviews, sprint retros, and roadmap check-ins tend to only count what got built. A team that treats deletion as a visible, credited outcome will actually do the cleanup instead of quietly letting the backlog of dead code grow because nobody gets recognized for shrinking a file.

Triage before you delete. Because dead-code detection is inherently a best-guess process, route findings through a real review step, especially for anything touching payments, auth, or automation where a false "this is dead" assumption is expensive. A mid-sized monorepo can easily surface hundreds of findings from a single Knip run; that is a backlog to work through deliberately, not a queue to auto-delete.

How to Apply This

  • Ask your engineering lead this week whether Knip (JS/TS) or Vulture (Python) is already running anywhere in CI, and if not, get one added as a non-blocking report first.
  • Add "dead code / duplication delta" as a line item in your quarterly engineering health review, right next to velocity and defect rate.
  • When reviewing an AI-assisted PR, ask explicitly: does this replace an old function, or does it leave one behind? Make "leaves one behind" a required follow-up ticket, not an assumption someone else will handle it.
  • In your next roadmap planning session, protect time for a "deletion sprint" the same way you'd protect time for a tech-debt sprint, and report the lines removed as a shipped outcome.
The same product manager fits a filter onto a conveyor belt, catching broken and duplicate code blocks

Getting ready for your next PM role means being fluent in these tradeoffs, not just feature roadmaps. Practice over 4,000 mock PM interviews, run a mock interview built from a real job description, and get your resume reviewed against that JD, all free at allthingspm.app.


References

PM
Written by the All Things PM team
Frameworks and interview prep for product managers.