Harshith Latchupatula

Constant Uncertainty

Living as a software engineer means accepting that you will almost never have the full picture.

The codebase is always larger than you've read. The system is always more interconnected than the diagram suggests. The requirements always contain a footnote you haven't found yet.

And yet somehow, things get built. Features ship. Bugs get fixed. Products reach people.

The discomfort is structural

It would be easy to assume that senior engineers feel certain. That at some point, the fog lifts and you finally know what you're doing. But I've noticed the opposite: the more experienced someone is, the more comfortable they seem with not knowing — and the faster they move despite it.

Certainty is a local maximum. It feels good in the moment but it means you've stopped exploring. The engineers I've most admired hold their mental models loosely. They make a call, note their assumptions, and stay ready to be wrong.

The goal isn't to eliminate uncertainty. It's to develop a better relationship with it.

Decisions under fog

Most engineering decisions are made with incomplete information. You don't know how users will actually behave. You don't know which performance bottleneck will matter. You don't know which abstraction will age well.

What you can do is:

  • Make your assumptions explicit
  • Choose reversible decisions over irreversible ones where the cost is small
  • Build feedback loops fast — prototype, instrument, deploy to a slice
  • Write down what you believe to be true before you look at the data

The last one is underrated. A small slice of real traffic teaches you more than a week of speculation. Reality is a better debugger than imagination.

A concrete example

Here's a pattern I've used when starting on an unfamiliar system. Before reading the code, I write out my mental model as a short note — what I think the data flow looks like, where I expect the bottleneck to be:

# Before reading auth.ts
# Hypothesis: token validation is inline, happens on every request
# Expect: middleware chain, probably JWT decode + DB lookup
# Unknown: where sessions are persisted (Redis? Postgres?)

Then I read the code. I'm almost always wrong about at least one thing. But the exercise forces me to have a model, which makes the corrections meaningful rather than just facts floating in a void.

This also works with inline notes when debugging. Before you add a console.log, write a comment with what you expect to see:

// Expect: userId is defined here, request passed auth middleware
console.log('userId', req.user?.id);

If the output surprises you, that surprise is information. If it confirms you, you've validated a model. Either way, you've learned something.

The trap of waiting

There's a specific anxiety that comes with uncertainty: the feeling that you should wait until you know more before acting. I've fallen into this more times than I can count.

It masquerades as rigor. It feels responsible. But usually, it's just fear wearing a lab coat.

The information you're waiting for often only becomes available after you've committed to something. You learn by doing, not by thinking about doing. The feedback loop requires an action to start.


This doesn't mean you act recklessly. It means you calibrate. Small bets first. Short cycles. Write the thing down and revisit it.

Uncertainty isn't a bug in how engineering works. It's a feature. It means the problem was actually worth solving.