Skip to content
Mahesh Kadambala
All articles

AI Engineering3 min read

AI-Assisted Engineering Without Losing the Plot

A year of using AI agents on production backend code: where they genuinely compress work, where they quietly create debt, and the review discipline that makes the difference.

AIProductivityEngineering PracticeCareer

I've spent the past year using AI coding agents on real backend systems — multi-tenant SaaS, Kafka pipelines, the unglamorous middle of enterprise software. Not demos. Code that pages someone when it breaks.

The honest summary: AI made me meaningfully faster, and it did so by changing which skills the job rewards, not by removing skill from the job.

Where it genuinely compresses work

Well-specified transformations. Migrations, mapping layers, test scaffolding, converting a REST controller's error handling to a new convention across forty endpoints. Anything where I can state the invariant precisely and verify it mechanically. This is a large fraction of enterprise work, and it's the fraction that used to eat afternoons.

First drafts of the boring-but-subtle. Testcontainers setup, Kafka consumer configuration, Flyway migration boilerplate. The agent's draft is 90% right, and I know exactly which 10% to interrogate because I've written these by hand for years. That last clause is the catch, and I'll come back to it.

Rubber-ducking architecture. Describing a design to an agent and asking it to attack the consistency story surfaces real gaps. It is a tireless, well-read reviewer with no ego. It is also confidently wrong in ways a colleague rarely is, which brings us to —

Where it quietly creates debt

Plausible-but-wrong at the boundaries. Agents are weakest exactly where systems are: at transaction boundaries, at concurrency, at failure modes. I've seen generated code that published Kafka events inside a rolled-back transaction — syntactically lovely, semantically the dual-write bug that the surrounding architecture existed to prevent. It compiled. Tests (that it also wrote) passed, because they tested the happy path.

Local coherence, global drift. Each generated change is locally reasonable; twenty of them produce a codebase with three ways of doing everything. Agents follow existing patterns when prompted with them and invent new ones when not. Codebase conventions now need to be written down — CLAUDE.md files, architecture notes, lint rules — because the agent, unlike your teammates, reads them every single time.

Skill amortization. My review of that Testcontainers draft is fast because of years of manual reps. An engineer who starts with the agent never builds the instinct that makes review cheap. I don't have a clean answer for this; I do think "write it by hand until it's boring, then delegate" is roughly right.

The discipline that makes it net-positive

One rule carries most of the weight: review generated code as if it were a PR from a brilliant new hire who has never seen production. Brilliant: don't waste review energy on syntax. Never seen production: check every transaction boundary, every retry, every tenant scope, every assumption about ordering and time. That is precisely the inverse of how it's tempting to review AI code, where the syntax is so clean it lulls you past the semantics.

Concretely, in our codebase:

  • Agents get the same guardrails as juniors: the type system, ArchUnit rules, integration tests against real infrastructure. Structural enforcement beats vigilance — same principle as making the safe query path the only path.
  • Prompts reference the codebase's own patterns ("follow the outbox convention in claims-service") rather than describing patterns fresh.
  • Anything touching money, auth, or tenancy gets written or line-by-line reviewed by a human. Not because agents always fail there — because failures there are unaffordable.

What this means for the job

The leverage moved up a level. Typing was never the bottleneck, but now it's visibly not the bottleneck: the job is deciding what to build, defining the invariants, designing the failure modes, and verifying that what was built honors them. Engineers who can specify precisely and review deeply are getting faster every quarter. Engineers whose value was translating tickets into syntax are competing with the agent.

That's not a threat, it's a direction. The plot to not lose: you own what ships. The agent is leverage on judgment, and leverage amplifies whatever it's applied to — including the absence of judgment.

Related articles

Architecture3 min read

Building an Enterprise Search Engine on the JVM

How we replaced unindexed SQL filtering with a custom query DSL compiled to tenant-scoped Elasticsearch queries — the grammar, the AST, the trade-offs, and what I'd do differently.

Distributed Systems3 min read

The Transactional Outbox, Properly

Dual-writes between your database and Kafka will lose events — quietly, rarely, and at the worst time. Here's the outbox pattern as actually implemented, including the parts the diagrams skip.