The unspoken assumption behind a lot of optimization is that faster is always better, so you keep going as long as you can find something to shave. But performance isn’t an open-ended good; it’s a requirement with a threshold, and past that threshold the returns don’t just diminish, they vanish. A response that takes a hundred milliseconds and one that takes ten feel identical to the person waiting, because both are below the point where a human notices delay at all. The nine milliseconds you saved are real in the profiler and invisible in the world. If nobody can perceive the improvement and no system depends on it, you didn’t make anything better — you spent effort and complexity to move a number that doesn’t matter.

This is why “fast enough” deserves to be an actual number, decided deliberately, rather than a vibe you optimize against forever. The number comes from the context: the thresholds of human perception for interactive things (the rough bands where a response feels instant, feels responsive, feels sluggish, or feels broken), a throughput a system has to sustain, a latency budget a downstream consumer requires. Once you name the target, optimization becomes a question with an answer — are we under it or not — instead of an appetite that’s never satisfied. And the answer tells you the most valuable thing a performance effort can know: when to stop.

Stopping matters because the cost of optimization is paid whether or not the speed was needed. Every optimization trades away some clarity — that was the through-line of these last two pieces — and when you optimize past the point of perceptibility, you pay that clarity cost in full and buy nothing. You’ve made the code harder to read, harder to change, more likely to hide a bug, in exchange for milliseconds no user will feel and no system will use. That’s not diligence; it’s a bad trade dressed up as craftsmanship, and it compounds, because the next person inherits the cleverness and has to preserve it while changing code that was never too slow to begin with.

There’s a symmetric failure worth naming, which is declaring “fast enough” without ever checking against a real target — shipping something that feels fine on your machine with ten records and falls over at the scale it actually runs. “Fast enough” is only meaningful measured against the requirement and the real input size, which is exactly why the number has to be explicit. The lazy version of “it’s fine” and the obsessive version of “make it faster” are the same mistake from opposite ends: both skip the step of naming what fast enough actually is, so neither can tell whether the work is done.

Put the three together and performance stops being a mystique and becomes a small, disciplined loop. You don’t guess about speed — you measure, because your intuition about what’s slow is wrong more than half the time. When you fix what’s slow, you change the shape of the work before you shave the constant, because at scale the shape is what dominates. And you optimize toward a named threshold and stop when you reach it, because past “fast enough” you’re only buying complexity. Know what fast enough is, find out whether you’re there, fix the growth if you’re not, and then leave it alone. Most performance work goes wrong by skipping the first step or never doing the last one.