Skip to content

Commit 54e7866

Browse files
committed
chore: remove defunct draft
1 parent 0f4098c commit 54e7866

3 files changed

Lines changed: 14 additions & 185 deletions

File tree

content/posts/2026/closing-the-alert-is-not-enough/index.md

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ If the checkout service starts timing out, you can often find the obvious broken
2222

2323
But clearing the alert only proves that the immediate symptom went away. It does not prove that the team understands the failure.
2424

25-
A complete investigation answers three questions: how it broke, why it broke, and why we thought it was a good idea to begin with. The best teams work through all three.
25+
A complete investigation answers three questions: what failed, what allowed it to fail, and what old constraint made the broken design seem reasonable. Skipping any of them leaves you guessing.
2626

27-
## Phase 1: Identifying the Mechanics
27+
## Phase 1: What failed
2828

2929
An alert is just a symptom. A 5xx spike, a crash loop, or a latency page tells you something is wrong, but it does not explain what failed.
3030

@@ -38,23 +38,21 @@ That level of detail matters because it narrows the problem from "the system is
3838

3939
Suppose checkout starts timing out during peak traffic. Metrics show the latency spike is isolated to one endpoint. Traces show most of the time is spent waiting on a database query. The query text has not changed, but the database plan has.
4040

41-
Now you have mechanics.
42-
4341
The service is not generically slow. One request path is issuing a query that scans far more rows than it used to. Under normal traffic, the query finishes slowly enough to be annoying but not slow enough to page anyone. Under peak traffic, it saturates the database connection pool and causes checkout requests to pile up.
4442

45-
Ideally, you can reproduce the issue. Reproducing the same traffic level, data shape, or race condition turns a theory into something you can test. It lets you prove your fix works instead of deploying a change and hoping the alert stays quiet.
43+
Ideally, you can reproduce the issue. Reproducing the same traffic level, data shape, or race condition turns a theory into something you can test.
4644

4745
But production failures are not always polite enough to be reproducible. Some depend on timing, traffic mix, bad data, cloud provider behavior, or a specific sequence of events that you may never recreate exactly.
4846

49-
When you cannot reproduce the issue, you still need a clear enough explanation to make predictions. What evidence should exist if your theory is correct? What metric should move? What log line should appear? What change should prevent the failure from happening again?
47+
When that happens, the next best thing is a theory that makes predictions. What evidence should exist if your theory is correct? What metric should move? What log line should appear? What change should prevent the failure from happening again?
5048

5149
That is the real goal of Phase 1: explain the failure well enough that your fix is not just a lucky guess.
5250

53-
## Phase 2: Finding the Conditions
51+
## Phase 2: What made the failure possible
5452

5553
Once you know how the system broke, ask why that failure was possible.
5654

57-
A timeout is not the whole cause. A nil pointer dereference is not the whole cause. A panic is not the whole cause. Those are consequences. They are where the system finally admitted something had gone wrong.
55+
A timeout, nil pointer dereference, or panic is not the whole cause. It is where the system finally admitted something had gone wrong.
5856

5957
The more useful question is: what conditions allowed this failure to happen?
6058

@@ -64,11 +62,9 @@ So you keep digging.
6462

6563
The query slowed down because an automated migration cleanup tool dropped an index it flagged as unused. The tool flagged it as unused because it only analyzed recent production traffic. It missed the seasonal promotion path, which only runs during large campaigns and uses a different filter pattern.
6664

67-
Now the investigation is getting somewhere.
68-
69-
The failed query matters, but the query is not the whole story. The deeper problem is that the system had an index that looked unused to automation but was still required by a low-frequency business process. The migration review process did not catch that distinction. The observability around index usage did not make it visible. The tests did not include the data shape that made the query expensive.
65+
The failed query matters, but the query is not the whole story. The dangerous condition was that the index looked unused to automation but was still required by a low-frequency business process. The migration review process did not catch that distinction. The available index-usage data did not make it visible. The tests did not include the data shape that made the query expensive.
7066

71-
That gives you a different class of fix.
67+
That changes what you fix.
7268

7369
You can restore the index. You probably should. Production is on fire, and nobody gets bonus points for admiring the flames.
7470

@@ -78,7 +74,7 @@ The point is not to find one magical "root cause" and declare the mystery solved
7874

7975
This is the useful part of the [Five Whys](https://en.wikipedia.org/wiki/Five_whys) technique: not mechanically asking "why" five times, but refusing to stop at the first plausible answer. Keep asking why until you find the conditions that made the failure possible, likely, or invisible.
8076

81-
## Phase 3: Understanding the Original Intent
77+
## Phase 3: Why the old decision seemed reasonable
8278

8379
This is the part most investigations skip.
8480

@@ -90,7 +86,7 @@ But code rarely enters a codebase as random nonsense. It usually solved a real p
9086

9187
Before you change the strange part, dig into the history. Run [`git blame`](https://git-scm.com/docs/git-blame), read the old pull request, search for the related ticket, and check whether there was an architecture decision record, or [ADR](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions). You are reconstructing the original engineer's mental model.
9288

93-
This is not about assigning blame. It is about [Chesterton's Fence](https://en.wikipedia.org/wiki/G._K._Chesterton#Chesterton's_fence): don't tear something down until you understand why it was built.
89+
This is not about assigning blame. It is [Chesterton's Fence](https://en.wikipedia.org/wiki/G._K._Chesterton#Chesterton's_fence) applied to software: don't tear something down until you understand why it was built.
9490

9591
```go
9692
// Why is this limit 47 and not 50?
@@ -113,28 +109,14 @@ That history matters.
113109

114110
Without it, you might remove a safeguard because it looks like dead code. You might "simplify" a limit that was quietly protecting a dependency. You might replace a weird workaround with a cleaner bug.
115111

116-
Understanding the original intent does not mean preserving the old decision forever. It means you change the system with your eyes open.
112+
Understanding the original intent does not mean preserving the old decision forever. It means you know which constraint you are removing, replacing, or deciding no longer matters.
117113

118114
Sometimes the conclusion is: this made sense then, but it does not anymore.
119115

120116
That is a good outcome. Now you can remove it deliberately, document why the old constraint no longer applies, and leave the next person a better trail than the one you found.
121117

122-
## The Payoff
123-
124-
Going through all three phases takes more time than closing the ticket, but it is how a team stops buying the same incident twice.
125-
126-
The first time, you fix a timeout.
127-
128-
The second time, you notice three teams have been fighting the same database assumption.
129-
130-
The third time, you stop treating it as a bug and start treating it as architecture.
131-
132-
That is the real value of a good investigation. It updates the team's understanding of the system. It turns one annoying failure into better tooling, better reviews, better tests, and better design constraints.
133-
134-
Not every incident needs a week-long archaeology project. Some bugs are small. Some fixes are obvious. Sometimes the right answer really is "we forgot to check for nil."
135-
136-
But when a failure exposes a surprising system behavior, a hidden dependency, or a piece of code nobody understands anymore, stopping at the failing line is too shallow.
118+
Not every alert requires a week of archaeology, but stopping at the failing line leaves the system ready to surprise you again.
137119

138-
The investigation is not done when the alert clears.
120+
The depth of the investigation should match the risk, but the habit should be the same: do not confuse the line that failed with the reason the system failed.
139121

140-
It is done when you actually learn something.
122+
Fixing the code restores the service. Understanding the context fixes the system.

0 commit comments

Comments
 (0)