Code that used to work stops working — not because anyone touched it, but because something it depended on did. It is the most common way software breaks after it ships, and the easiest to miss until a user finds it first.
One passing build, one unrelated change, and a metric that quietly drops — until something catches it.
A regression is rarely one moment — it's five, and only the last two are visible without the right tests.
Feature behaves correctly and is covered, or assumed to be.
A different feature, dependency, or config is touched nearby.
No error, no crash — just a wrong result somewhere untested.
A test fails, or worse, a user reports it in production.
Root cause patched; a test is added so it can't happen twice.
Four causes account for most regressions — none of them require anyone to touch the broken code directly.
A function edited for one call site changes behavior for every other caller relying on it.
A transitive package bumps a minor version and quietly changes a default.
Staging and production disagree on a config, flag, or data shape.
An old branch reintroduces a bug that was already fixed on main.
The bug doesn't get harder to find — it gets harder to trace, reproduce, and safely undo the further it travels.
None of this eliminates regressions — it shortens the distance between introducing one and knowing about it.