Taxonomy Matters
Not all bugs are created equal.
When something breaks in a system, the first instinct is to jump into the code and start poking around. This is like a doctor performing surgery before diagnosing whether the patient has a broken bone or a virus. The treatment for each is radically different, and applying the wrong one wastes time — or makes things worse. The single most valuable skill in debugging is not knowing how to use a debugger; it is knowing how to classify the failure you're looking at.
In the 1960s, computer scientists began borrowing names from physics to categorize software bugs. These names stuck because they capture something essential about how each type of bug behaves. A "Bohrbug" is named after Niels Bohr's deterministic atomic model — it's predictable and repeatable. A "Heisenbug" is named after Werner Heisenberg's Uncertainty Principle — observing it changes its behavior. These aren't cute nicknames; they're diagnostic categories that tell you which tools and strategies will actually work.
By naming the type of anomaly, you determine the correct strategy to resolve it. A Bohrbug yields to systematic reproduction and unit tests. A Heisenbug requires tracing and reasoning about concurrency. Software rot demands continuous maintenance and dependency management. In this module, we explore the physics of failure: consistent failures, transient failures, and the slow decay of working code. These categories apply whether you're debugging a Python script, a Kubernetes deployment, or a distributed microservices architecture.
Key Point: In incident response and post-mortems, the first question should never be "What's the fix?" It should be "What kind of failure is this?" The classification determines the investigation method, the tooling, and the timeline for resolution. Misclassifying a Heisenbug as a Bohrbug and spending three days trying to reproduce it deterministically is one of the most common and costly debugging mistakes in production systems.