The Engineering Bottleneck Has Moved
byKadhir Mani
(4.8 minutes)
<section data-section-id='f99e031a-87d7-4d28-bab3-c8b339ad3fbf'><p><span style="white-space: pre-wrap;">For most of my career, I treated engineering decisions like they were carved in stone the moment I made them.</span></p><p><br></p><p><span style="white-space: pre-wrap;">Choose the wrong abstraction, and you'd pay for it for years. Pick the wrong service boundary, and you'd be untangling it for quarters. That cost shaped everything:</span></p><ul><li value="1"><span style="white-space: pre-wrap;">how carefully we specced</span></li><li value="2"><span style="white-space: pre-wrap;">how many reviews we ran</span></li><li value="3"><span style="white-space: pre-wrap;">how long we waited before committing to anything</span></li></ul><p><br></p><p><span style="white-space: pre-wrap;">I don't think that instinct is wrong, exactly, but I think it's become less relevant these days. AI-assisted development has made the first pass so cheap that the bottleneck has quietly shifted. The expensive part is no longer writing the code. I think it's now knowing what to write, catching what's subtly wrong, and deciding what actually matters.</span></p><p><br></p><p><span style="white-space: pre-wrap;">In other words, caution used to be important, especially at scale, but I think judgment takes its place now. The last few months especially changed how I think about engineering.</span></p><p><br></p></section>
<section data-section-id='30b3ec62-6f1f-4747-a80d-9b26da2d5104'><h2 id="before-and-after-mindset"><span style="white-space: pre-wrap;">Before and After Mindset</span></h2><p><span style="white-space: pre-wrap;">Before AI-assisted development, dependency changes and debt cleanup carried a specific cost: attention and risk, not just time. Touching an interface meant auditing every downstream consumer first. Refactoring a core module meant mapping the call sites and absorbing anything that was missed.</span></p><p><br></p><p><span style="white-space: pre-wrap;">I guarded the design, deferring cleanup, defending abstractions longer than was healthy, because disruption required effort I couldn't justify mid-sprint.</span></p><p><br></p><p><span style="white-space: pre-wrap;">But now, AI makes validation, migration, and refactoring cheap enough to try, inspect, and undo. I can draft a migration path, review the diff, and abandon the approach in an afternoon if it's wrong. No real time or effort lost.</span></p><p><br></p><p><span style="white-space: pre-wrap;">Speculative refactors I used to defer indefinitely now happen in the same session as the feature work that exposed them.</span></p><p><br></p><p><span style="white-space: pre-wrap;">The real shift for me is where we can spend our attention. When touching code is expensive, you protect it. When it's cheap, you can explore it.</span></p><p><br></p><p><span style="white-space: pre-wrap;">Wariness now belongs only to decisions genuinely hard to reverse: data migrations without rollbacks, API contracts with external dependents, architectural choices baked into topology. Everything else is fair game, and that changes how I think about design from the start.</span></p><p><br></p></section>
<section data-section-id='1cd31f23-9864-4d34-9717-d62f125d60e1'><h2 id="three-specific-shifts"><span style="white-space: pre-wrap;">Three Specific Shifts</span></h2><p><br></p><collapsible-card data-icon="layers" data-title="Dependencies: patch or fork without fear" data-default-collapsed="true"><p><span style="white-space: pre-wrap;">The old instinct was purity: pin exact versions, avoid forks, treat every upstream dependency as sacred. My new instinct is more pragmatic. AI-assisted validation makes it cheap to test a locally patched dependency against your surface area in seconds. And better yet, the models help make migrating off dependencies just as easy, so you're never truly locked in. "Try it, then move on" beats waiting for upstream, especially because you ask the model to migrate you back to the upstream when it's ready.</span></p></collapsible-card><p><br></p><collapsible-card data-icon="settings" data-title="Debt: lighter, not weightless" data-default-collapsed="true"><p><span style="white-space: pre-wrap;">The old instinct was to hoard cleanup work for dedicated sprints. Debt was expensive to pay down, so you batched it or ignored it. My stack primarily consists of Devin, Cursor and Codex, which makes refactors and style fixes happen super quick. I still like having code that's easy for a human to read, just in case we need to dig into a gnarly bug. That incremental cleanup is now viable between features, not just in dedicated cycles. That changes the calculus: debt is less scary, less something to defer. But it's still real — AI tools compress the effort, not the judgment required to know what to fix and when.</span></p></collapsible-card><p><br></p><collapsible-card data-icon="layout" data-title="Interfaces: stop designing for screens first" data-default-collapsed="true"><p><span style="white-space: pre-wrap;">Chat and agent surfaces punish screen-centric thinking. If your product's core logic is tightly coupled to a specific UI shape, you'll rebuild it every time the interaction model shifts — and right now, interaction models are shifting fast. The new instinct is to treat UI as a thin, disposable layer over well-defined behavior. Build systems that are easy to change or delete. Invest in the semantics of what your system does, not the pixels of how it looks. Over-engineering a fixed interface is the new premature optimization.</span></p></collapsible-card><p><br></p></section>
<section data-section-id='22a15ee0-de60-432c-9b91-01f6d81f8893'><h2 id="implications-for-team-practices-and-what-still-matters"><span style="white-space: pre-wrap;">Implications for Team Practices and What Still Matters</span></h2><p><span style="white-space: pre-wrap;">AI-assisted development compresses iteration cycles, which changes how we strategize in engineering, not just how we write code.</span></p><p><br></p><p><span style="white-space: pre-wrap;">Implications for our team so far:</span></p><ul><li value="1"><b><strong style="white-space: pre-wrap;">Delegate more aggressively.</strong></b><span style="white-space: pre-wrap;"> Generation is cheap, so juniors can own more surface area. Your job shifts from writing to setting constraints and reviewing outcomes.</span></li><li value="2"><b><strong style="white-space: pre-wrap;">Review for risk, not style.</strong></b><span style="white-space: pre-wrap;"> Code review becomes "what fails at scale or under load," not "how did you write this."</span></li><li value="3"><b><strong style="white-space: pre-wrap;">Choose reversible dependencies.</strong></b><span style="white-space: pre-wrap;"> Fast iteration exposes bad lock-in fast. Prefer contracts you can swap in a sprint.</span></li><li value="4"><b><strong style="white-space: pre-wrap;">Design for deletion.</strong></b><span style="white-space: pre-wrap;"> AI-generated code gets replaced more often. Modular, bounded design isn't just elegant, it's more practical now than it's ever been.</span></li><li value="5"><b><strong style="white-space: pre-wrap;">Teach taste, not syntax.</strong></b><span style="white-space: pre-wrap;"> Mentorship shifts toward helping engineers recognize plausible-but-wrong output.</span></li></ul><p><br></p></section>
<section data-section-id='c918ae89-a7f7-4ac5-bc2e-fedfe37b4696'><p><b><strong style="white-space: pre-wrap;">What still matters</strong></b></p><p><span style="white-space: pre-wrap;">AI can write code faster than ever, but that doesn't mean it gets things right. It often produces code that runs without errors, yet still solves the wrong problem. Someone still has to read it, maintain it, and catch those mistakes. That someone is you.</span></p><p><br></p><p><span style="white-space: pre-wrap;">A few things haven't changed:</span></p><ul><li value="1"><span style="white-space: pre-wrap;">You still need to decide what the right solution looks like. AI doesn't understand your business needs as well as you do.</span></li><li value="2"><span style="white-space: pre-wrap;">Code should still be readable. If something goes wrong and you need to step in and debug it yourself, you'll be glad you can follow what it's doing.</span></li><li value="3"><span style="white-space: pre-wrap;">Only real people understand what users are actually struggling with. AI can't feel that.</span></li><li value="4"><span style="white-space: pre-wrap;">Moving faster is great, but the final call still belongs to a human.</span></li></ul><p><br></p><p><span style="white-space: pre-wrap;">The tools sped up the work. The judgment is still yours.</span></p><p><br></p></section>
<section data-section-id='dc64f566-2800-4a1d-b643-f3c5526854b4'><h2 id="final-thoughts"><span style="white-space: pre-wrap;">Final Thoughts</span></h2><p><span style="white-space: pre-wrap;">AI doesn't remove the hard work from engineering. It relocates it. The hours that once went into untangling legacy code, patching brittle integrations, and maintaining systems that nobody fully understood can now go toward something better: understanding users, designing adaptable architectures, and building things that actually matter.</span></p><p><br></p><p><span style="white-space: pre-wrap;">The maintenance tax isn't gone, but it's shrinking. What you do with that reclaimed attention is the real question, and the engineers who answer it well are the ones who'll define what this era of software development becomes.</span></p><p><br></p></section>