AI Wrote the Code. I Still Had to Do the Thinking.

AI is a powerful tool. Left alone, it’ll happily write code that’s well structured, compiles, runs, and looks well engineered. It’ll confidently explain why its solution is sound.

That is what makes it dangerous.

Engineering is more than producing code that works. It is understanding systems, questioning assumptions, weighing trade-offs, and recognizing when a convincing answer does not survive scrutiny.

AI is exceptionally good at producing plausible, well-reasoned solutions.

But:

  • plausible ≠ correct
  • complete ≠ appropriate
  • confident ≠ right

Here are four times engineering judgment changed the outcome.

Case Study 1: When Versioning Was the Wrong Fix

The problem

I inherited a system where the same piece of content existed in two places: one version on the frontend and another on the backend.

That split had been introduced by developers who came before me, so the immediate problem looked like synchronization. The app could show one version while the backend generated or stored another.

The deeper problem was that the system had two sources of truth in the first place.

What the AI proposed

The AI proposed a full versioning-and-hashing scheme:

  • Compute a content hash on the backend.
  • Add a persisted field to store that version on each record when it was captured.
  • Add reconciliation logic to compare the stored version with the current one and detect drift.
  • Add tests for the field, hashing behavior, and comparison paths.

Why it sounded reasonable

Every piece was defensible in isolation. It solved the problem as the system had already framed it: keep two copies of the same content synchronized.

It sounded responsible: versioning, hashing, audit trail.

If I had skimmed the diff, I probably would have nodded along. The approach likely would have worked and produced the desired behavior.

But it also would have quietly preserved the original design mistake. The AI accepted the existing split as a fixed constraint and set out to make that split more elaborate instead of asking whether it should exist at all.

Where Engineering Judgment Made the Difference

Why has this gotten so complex? The screen should just show the content from the backend.

The AI had accepted the existing architecture as a constraint and optimized within it. My instinct was to question the constraint itself. Before adding more machinery, I wanted to know whether we needed the machinery at all.

The real solution

I stopped treating the inherited split as something the system had to preserve.

The backend became the single source of truth. The frontend simply fetches the current content from the backend and renders it.

That removed the opportunity for drift instead of building machinery to detect it. There is no stored version, no hash, no reconciliation step, and no cross-system versioning contract to maintain.

The correctness is structural because there is only one authoritative source.

The cost of following the AI

  • A schema migration, forever. A new database column would need to be deployed everywhere and maintained indefinitely.
  • A backfill problem. Existing records would need a version assigned. What version? Based on whose interpretation of history?
  • A new invariant. Every write path would need to set the version correctly forever. Missing one would create silent bad data—the exact class of bug I was trying to avoid.
  • More failure modes. Drift detection has its own edge cases and false positives. I would have added a second system that could be wrong in order to monitor the first.
  • Permanent test surface. Those tests would need to be understood and maintained through every future refactor.
  • A cross-system contract. Frontend and backend would need to stay aligned on a versioning scheme whenever the content changed.
  • Cognitive tax. Every engineer touching the feature later would need to understand all of it before making a safe change.

What I learned

AI tends to optimize for solutions that look thorough. Thorough-looking code reviews well.

It also tends to accept the existing shape of a system as part of the problem definition. In this case, it happily perpetuated an inherited design instead of questioning whether that design was still necessary.

But every new field, branch, migration, and test has a lifetime cost. The better solution was not the one that synchronized two sources most comprehensively. It was the one that made synchronization unnecessary by restoring a single source of truth.

Case Study 2: The Feature That Was Safely Turned Off

The problem

I needed a switch that forced a behavior in the frontend. The whole reason the work existed was to make that enforcement happen.

What the AI proposed

The AI implemented the gate, then recommended shipping with the switch off.

Its reasoning was textbook-clean: off is the safe default; I would not want to unexpectedly block anyone.

Why it sounded reasonable

That is normally prudent advice. Feature flags often should default to off. A cautious rollout is usually better than an accidental broad impact.

But this was not a generic feature flag. The work existed specifically to turn this enforcement on.

Where Engineering Judgment Made the Difference

The whole point of this feature is to turn it on.

The recommendation sounded reasonable because it was based on a common engineering practice. But good engineering isn’t about applying best practices in isolation. It’s about applying them in service of the goal.

The real solution

I treated the business objective as the constraint, not a generic best practice. The gate shipped in the state that actually enforced the behavior it was built for, with the rollout controls appropriate to that goal.

The cost of following the AI

  • A no-op release dressed as a win. The feature would ship, the deploy would go green, and the intended behavior would never happen.
  • A silent gap between “done” and “working.” Nothing would error or alarm. The switch would simply leave the capability inert.
  • The original problem would continue. The business reason for the feature would remain unaddressed until someone noticed.
  • Expensive rediscovery later. Eventually someone would ask why it was not working and spend time re-deriving that the flag had been set the safe-but-wrong way.
  • A credibility hit. “We built and shipped that” followed by “it turns out it never ran” erodes trust in the whole effort.

What I learned

I had already told the AI what I wanted: the whole point was to turn this thing on. It told me to leave it off anyway, with a perfectly reasonable-sounding explanation.

That is where engineering judgment matters. The model does not hold the goal the way I do; it reaches for what sounds safest in the moment. I am the one who remembers why we are doing the work, recognizes the mismatch, and says: no, that is backwards.

Generic best practices are not substitutes for context.

Case Study 3: The Threshold Was a Red Herring

The problem

I had an enforcement feature that was supposed to block outdated client apps, but it only worked some of the time. The same request would be blocked on one server instance and waved through on another.

What the AI proposed

The AI immediately focused on the minimum-supported-version threshold. It suggested raising the threshold so old clients would fall below it and get blocked.

Why it sounded reasonable

The feature did use a version threshold. “The threshold is set wrong” is an easy story to accept, especially when the symptom is that old clients are getting through.

Where Engineering Judgment Made the Difference

If these clients do not even report a version, why would changing the threshold fix anything?

The explanation sounded internally consistent, but it didn’t account for everything I already knew about the system. That mismatch was enough to stop treating the recommendation as an answer and start treating it as a hypothesis.

The real solution

The threshold was a red herring. The clients I cared about predated the feature and did not report a version at all.

The real problem was that some server instances booted with incomplete configuration and silently fell back to defaults. Fully configured servers blocked clients correctly; half-configured ones let everyone through. It had nothing to do with the version number and everything to do with which instances came up healthy.

That was why it looked random.

The cost of following the AI

  • A fix that looked like it worked. I could have raised the threshold, watched healthy instances behave correctly, and called it done while part of the fleet still let outdated clients through.
  • The real fault buried under a “fixed” label. Misconfigured instances would continue to appear intermittently, now with less reason for anyone to investigate.
  • Collateral from turning the wrong knob. Raising a threshold can block clients I never intended to block.
  • Time bleeding away. Every hour spent on the wrong lever is another hour the outdated clients keep slipping past the feature built to stop them.

What I learned

The AI sounded just as certain when it was wrong as when it was right. There is no wobble in its voice when it is guessing.

What saved me was not a cleverer prompt. It was knowing the system well enough to feel that the story did not add up, and being willing to argue with a confident machine instead of doing what it said.

Evidence beats confidence.

Case Study 4: The Root-Cause Fix With the Wrong Blast Radius

The problem

I was dealing with another boot-time configuration failure: some instances came up with incomplete configuration.

What the AI proposed

The AI proposed fixing the issue “at the source”: upgrade the shared component that delivers configuration to every service, plus make a platform-wide setting change.

Why it sounded reasonable

Technically, it sounded more complete. “Fix the root cause” sounds more correct than “add a guard.”

But the component was shared by every service in every environment. There was no way to upgrade it only in a test environment. The change would affect production at the same moment, with nowhere to prove it first.

Where Engineering Judgment Made the Difference

How can we test this in isolation without changing production, especially when we have no direct evidence it will even solve the problem?

At that point the discussion stopped being about technical completeness and started being about something more important: how much confidence we had that it would work, and how much risk we were willing to take to find out.

The real solution

I held the scope line: do not touch the shared component or production yet. Ship the small guard, prove it in isolation, and leave the big swing for later.

When I investigated the shared component’s behavior, the versions the AI wanted to jump between handled this failure identically. The proposed upgrade almost certainly would not have fixed anything.

The small guard was a few reversible lines, testable in a sandbox, and made the dangerous state impossible to serve - whether or not the upstream component was ever changed.

The cost of following the AI

  • No safe place to prove it. A shared component meant changing production behavior without staging evidence that the change worked.
  • An all-at-once failure mode. If the upgrade regressed, every service relying on that component could regress together.
  • Coordination tax for a maybe. Change windows, rollback plans, and broad sign-off would be real overhead spent on an unproven fix.
  • A difficult rollback. Reverting shared infrastructure during an incident is very different from reverting a few lines in one service.
  • The worst part: it was probably useless. That risk bought little because the underlying behavior showed the upgrade would not solve the problem.

What I learned

The AI graded the options on technical completeness. It did not weigh blast radius, reversibility, or churn, and it did not stop to ask whether the impressive-sounding fix would actually work.

Those are the questions I have to ask: What is the smallest safe step? Can I prove it somewhere contained? How hard is this to undo if I am wrong? Is the “real fix” actually real?

The model optimizes for the impressive-sounding answer. The person accountable for production has to optimize for the safe one.

Conclusion

AI has fundamentally changed how I write software.

It helps me move faster, explore ideas more quickly, and often points me toward approaches I would not have considered.

But these experiences reminded me that my value is not measured by how quickly I can produce code.

It is measured by whether I am willing to stop, ask one more question, and refuse to accept a convincing answer until it survives scrutiny.

AI can generate solutions.

AI helped me write every one of these solutions faster. It didn’t make the decisions for me.

In every case, writing the code was the easy part.

The judgment wasn’t.

That's the work we do every day. AI is an incredible tool. We use it constantly. But our clients don't hire us to generate code—they hire us to apply engineering judgment, challenge assumptions, and build solutions that stand up to scrutiny. If that's the kind of engineering partner you're looking for, let's talk.