A bug showed up in my personal project last month. Nothing dramatic - a value wasn't updating the way it should have been.
I opened the file. I re...
For further actions, you may consider blocking this person and/or reporting abuse
Here's the balance. Every line of code written is a quantum of risk; in a team you are constantly taking risks on other team members. I have 13 engineers in my team; do I need to understand what each of them made? I think your argument is that it's me taking the risk with AI, well it's me taking the risk with them too - I'll ask them to fix a problem we find, we'll review big architectural decisions, but no way am I reading every line of code and fully getting it - that's what they do. We all make mistakes. The best way to avoid mistakes is great testing strategy and good architecture.
Outsourcing to AI is the same problem to me as outsourcing to my team, and that works on down the stack I think.
No matter whether the human who crafts the code by hand or the AI does, It's the team lead who is responsible for reviewing the code. Well, it's in-fact the human being who is accountable for and not the "AI".
Agreed. As the CTO it's my accountability. But it's my accountability to ensure the code is of a high enough quality - not that a human reviewed it.
Yes, Welcome to the accountability ladder 😀
AI is just another tool.
this is a fair challenge, and honestly it made me think harder about where the line actually is.
here's the distinction I keep landing on though when one of your 13 engineers writes something you don't personally understand, the understanding still exists in them. you can ask. they can explain the tradeoff, the edge case, the why. the risk is distributed, but it's not absent.
with AI, if the person prompting it doesn't build that understanding, there's no one left to ask. the model doesn't have a persistent mental model of the decision it made five minutes ago, let alone five months later. it's not outsourced understanding at that point it's just missing understanding, full stop.
so I'd actually agree with you on architecture and testing being the real safety net at team scale that's the right level of abstraction for managing 13 people's code. my argument is narrower: it's aimed at the individual developer prompting AI directly, where the temptation is to skip the "does someone understand this" question entirely, not delegate it to a person who does.
good testing and good architecture absolutely reduce how much any single line needs personal understanding. I just don't think they replace the need for someone to have it.
It comes down to AI being the junior dev (in conventional software companies) and you're the senior dev. Your job is to have a thorough enough understanding of everything to skim through their code and pick up any flaws. If you dont know what it's writing, it's because you lack the knowledge and should probably review it's code more often to get a thorough understanding of what, why, when, where, how, who.
The knowledge debt is real, but it's entirely on us as developers. We just 'trust' .net framework to do it's job, because it's compiled and validated by millions. But if you've ever dealt in-depth with python, you'd know that more often than not, packages arent as bulletproof and if you want them to work right, you need to make edits to them just to get them working. That requires an incredible amount of knowledge regarding what and how it's doing it.
Essentially, if you take a loan, you need to repay that loan, incrementally, or default when it builds up too much. What you save in writing it, you need to spend on reading it. Except it's a negative interest rate. The more you read and review, the less it costs you to do so. Compounded over an entire project, you get a net-gain. You gain knowledge, speed and accuracy, by understanding that AI makes mistakes and you should review every single thing it does explicitly. Unless of course you build guardrails for it yourself, so you know exactly what's possible and what isnt.
Negative interest rate is a genuinely sharp reframe the more you review, the cheaper reviewing gets, because you're building the mental model that makes the next review faster. that compounds in the opposite direction from how I framed it, and I think you're right.
the NET vs Python packages comparison is a good way to ground it too. trust scales with how battle-tested something is, not with how confident it looks. AI-generated code hasn't earned that trust yet, no matter how clean it reads which is exactly why treating it like a junior dev's PR, not a senior dev's, matters.
where I'd push back slightly: the senior junior framing works well for a single PR, but the failure mode I was pointing at is more about compounding neglect than a single skipped review. reviewing thoroughly once is a habit. reviewing thoroughly every time, on the 50th feature when the deadline is tight and the code looks fine that's where the debt actually accumulates, even for developers who genuinely have the knowledge to catch it.
the guardrails point is the real answer though. if you've built the constraints AI has to operate inside, you've effectively moved the trust from reading every line to trusting the system that bounds what lines are possible which is a much better place to end up.
I'd have to push back on that 1. That's a choice. "When is work considered done" in other words. Deadlines are deadlines, but you wont ship code with compile errors, nor should you ship AI generated code that hasnt been validated. AI sped up writing it enough that you can afford to take the time to review it properly. If you cant do that within the deadline, then the deadline was fundamentally too tight to fit. Zero-compromise on quality is what the standard is for 2026 developers, we have to review EVERYTHING the AI writes, because it will make mistakes and it will compile perfectly while doing so. If you wrote it yourself, it would still take you 10x longer than it would reviewing it thoroughly. So the net-gain is still there, but if you try to push to the bleeding edge of speed, you will bleed quality with every PR. Validation is non-optional, that 50th feature when deadline is tight, is exactly when zero-compromise mindset should kick in, because you already wrote 49 features that gave you ample time to reflect and fix any outstanding issues, nr 50 is the critical check, because if you were thorough with your reviewing for 49 features, that last 1 shouldnt take you any longer than any 1 of those, but trying to skip a check, is a recipe for disaster and a 5 min late PR is better than a broken PR, because the day the error surfaces, it'll take 100x the time to fix it, because the system has expanded since then.
If you want to work with AI, you need to be the structure that contains it. You are the final validation layer, you are the one who scopes features accurately so it doesnt bleed over, you are the one who instructs, it follows your command to the best of it's ability. If that's too much responsibility for you, then write guardrails that limit the scope you need to worry about, so instead of reviewing 100 lines for every single possible mistake, you know 90% of the coverage is cleared by guardrails and you just have 11% worth to validate (11%, because there's always 1% you didnt account for).
Take linting mistakes. You can wire up a linter check that covers it, you can trust it, so you dont have to validate it. Syntax, is the same. Unit Tests and Integration tests cover even more ground for you. If you really want it to be robust and limit what you actually need to check, dont rely on AI generated code, rely on AI initialized automation macro generated code (eg. Roslyn). You define the setup, you validate your framework, now it's 1 less headache. Take V.A.L.I.D. for instance, I wrote it to replace CSLA, then I built the generator for it, so it's easier to use, now it generates 82% of my codebase, making sure that the UI-DAL-BO-Rules-Endpoint-UnitTests-FuzzerTests-MCP setup is flawless every single time. It took me months to build, but it saves me 80% of my time and tokens doing anything on from that day and better yet, I can trust it to be accurate 100% of the time.
A 5 min late PR is better than a broken PR that's the line that actually settles the argument. I was treating deadline pressure as a fixed constraint that review time has to bend around. you're right that it's a choice about what done means, and that's a much more honest way to frame it.
the guardrails math you laid out linting covers X tests cover Y leaving you a smaller surface to actually think about is exactly the shift from review everything manually to review what the system can't already guarantee. that's a genuinely better architecture for trust than what I described.
V. A. L.I.D. generating 82% of your codebase with that level of guaranteed correctness is a strong example of what "the structure that contains it" actually looks like in practice, not just in theory. months of upfront investment for that kind of compounding return is exactly the trade the article was gesturing at without spelling out how to build it.
I think the difference between us is smaller than it looked a comment ago you're describing the mature version of what I was calling paying down the debt build the guardrails once, review only the genuine gap, and treat zero-compromise as non-negotiable rather than aspirational. that's a sharper standard than mine.
The gap isnt big, the gap is just a 1 liner, 'when is it done'. If you say when it's compiled, you're wrong and it'll bite you later. If you say it's after you've reviewed it, you're wrong and it'll bite you all the same later. If you say it's after you've reviewed and validated it, then you're safe(r). AI makes mistakes, so do we and reviewing covers some of the bases, but not all, because it's just another model (you) reviewing the code. You cant guarantee the AI's correctness any more than you can your own for reviewing it, because it 'looks right' is alot different than 'it is right'. That's why the guardrails are your ownly guarantees and using tools like Roslyn to write code will always produce better results than having AI write it itself. Case in point, when an AI has to do a massive edit across files, it writes a python script, instead of doing 100 edits manually. It can trust the script more than it can trust itself to remember the task at step 99. Sure it saves tokens, but context is more important than token burn. 100 identical fixes dilutes it's memory into being fixated on it. Whereas a script is just a single memory.
It's like trusting a toddler on a bicycle to not fall, correcting them and correcting them, hoping for the best, instead of putting on side wheels to guarantee it
The concept of micro loan is in-deed very interesting. However, before buying a loan, it's the responsibility of the human to ask questions. I am going to literally consider a laymen human and their loan taking approach 😁
This is a genuinely great extension of the metaphor especially 6. borrowing more loan from someone else is exactly what happens when you ask AI to explain AI's own code instead of actually understanding it yourself. you haven't paid the debt, you've just refinanced it.
might steal this whole framework for a follow-up 😁
The part that landed for me is that the code was clean and still unfixable, because cleanliness and understanding are two things you were paying for separately. I've started treating a generated diff as unmerged until I can explain out loud why it works, which catches the borrowed-understanding gap before it compounds. Do you have a lightweight habit that forces that, or is it discipline in the moment?
Cleanliness and understanding are two things you were paying for separately that's a sharper way of saying what the article was reaching for. clean code buys you readability. it doesn't buy you comprehension. those got conflated for me for a long time.
the unmerged until I can explain it out loud rule is close to what I actually do, but I'll be honest it's mostly discipline in the moment, not a system. the closest thing I have to a habit rather than willpower: I do it right after generation, before moving to the next file. if I let even one more file get written in between, the explanation check quietly turns into a formality instead of a real one, because my attention's already moved on.
the other thing that's helped more than I expected: if I can't explain a piece in under a minute, I don't debug my way to understanding it later I rewrite that specific piece immediately, even if it technically works. rewriting forces the model to actually form. re-reading doesn't, for me at least.
still mostly discipline though not a system that runs without me. curious if you've found anything that survives you being tired or rushed, because that's usually where mine breaks.
Curious whether others have noticed this too:
AI seems to reduce the time spent writing code, but increase the importance of understanding architecture. The less time I spend typing, the more valuable it becomes to understand the boundaries, invariants, and data flow of the system. That's where most of my debugging time goes now.
yes and I think this is the shift that most AI makes you faster takes completely miss. it's not that skill requirements went down, they moved. the skill that used to be partially covered by the slow, forced act of typing every line building a feel for boundaries and data flow just by having to type your way through them now has to be built deliberately, because generation speed skips right past that friction.
that's where most of my debugging time goes now matches what's come up elsewhere in this thread too. the bugs people are hitting aren't usually syntax or logic errors within a single function anymore they're architecture-shaped bugs, where the code is locally fine and the invariant it silently depended on somewhere else got violated. that's a much harder category of bug to catch by reading any single diff carefully, which is probably why it's eating more of your time than the actual writing ever did.
The explanation check is the right instinct, and it has one false-positive mode worth closing, because it is the exact mode AI code exploits. "Could I explain this right now" measures whether you have a model of the code, not whether you have the right one. Generated code is fluent and plausible by construction, so it reads as if it means what you would expect, which means you can produce a confident explanation that is wrong. You skim the function, it looks like it does X, you explain X cleanly, and it does X-prime in the edge case you did not read for. The check passes, and now you have certified the debt as paid, which is worse than knowing it is outstanding, because a debt you think you cleared leaves the ledger.
It fails because the check reads the same fluent surface that created the risk, so it inherits the risk's blind spot. Your ability to explain the code is correlated with how plausible it looks, not with whether it is correct. The fix is to decorrelate the check from the fluency: not can-I-explain-it, which reads your own model, but did-my-prediction-match, which the code cannot fake. Before running it, say what it returns on one specific input, or state the invariant you think it holds and write the input that would break it, then run it. A prediction is falsifiable by the code. An explanation is not, it only has to sound right, and sounding right is precisely what the generator optimized for. Your own weeks-long bug is the clean case: you could have explained that code any day that week and been wrong, because skimming produces explanations and nothing forced your model to touch reality until the bug did. The bug was a prediction check you did not run on purpose.
Your own weeks-long bug is the clean case: you could have explained that code any day that week and been wrong that's uncomfortably accurate, and it's the exact failure mode the article never named. I passed my own explanation check the whole time. I just wasn't checking against reality I was checking against a plausible story my own reading had constructed.
the distinction between can I explain it and did my prediction match is sharper than anything I've used so far in this thread. explanation is unfalsifiable by design it only has to be internally consistent with itself, not with the code's actual behavior. prediction forces contact with the thing you're supposedly verifying. that's the difference between reading comprehension and an actual test.
A debt you think you cleared leaves the ledger might be the single best sentence in this entire comment section. false confidence isn't neutral, it's worse than acknowledged uncertainty, because at least uncertainty keeps you looking. certainty stops the search.
I think this replaces the rule I'd give people now don't ask if you can explain the code, state what a specific input returns before you run it, and see if you're right. that's a test AI-generated fluency can't pass by just sounding plausible.
Explanation is unfalsifiable by design is exactly it, and it is worth keeping because it names why the swap works: a prediction has a failure mode an explanation does not, it can be wrong in a way you cannot talk your way out of, because the code returns what it returns and does not care about your story.
One guard so the new rule does not re-import the old hole at a different layer: a prediction is only as good as the input you pick. Predict the happy path and it passes for the same reason the explanation did, you predict X, it returns X, both of you blind to the edge case neither looked at. So the rule is not just state-what-it-returns-then-run, it is state it for the input you are least sure about, the one where your model of the code is thinnest. The boring input tests your reading comprehension a second time. The input you are nervous about is the one that tests the code. Same move you already landed, just aimed where the debt actually hides.
We thankfully had only very small moments of this happening in our project. The reason is that the thing you've discovered, we've been doing from the beginning. We put it this way: If you make the GIT commit, it's your code. The AI doesn't own the code it generates for you, you do. It's all about ownership, really.
You can't take ownership of something you don't understand. So you have to dig in and understand it if you want to own it. And like it or not, as you found out: You own it. The AI isn't accountable for anything, they even tell you so outright in all their warning messages about how AI code can have bugs.
Me and my colleague choose to stay on the slower, but safer side of the spectrum: We own everything we check in, so we also understand everything we check in. With very, very few exceptions and even then only if the automated test unambiguously shows that it works. We can also afford to do this because we work on a very critical product, where correctness rules and speed is only a secondary concern (to us).
So I think with AI, there is always this balance: How much can you afford to just trust it in the name of speed, and how much do you have to check? In critical systems, you're on the safety end of the spectrum. In throwaway systems, you're on the speed end of the spectrum.
And most software is probably somewhere in between.
The AI doesn't own the code it generates for you, you do that's the cleanest one-line summary of the entire article. ownership is the right word for it, sharper than understanding because ownership implies accountability, and accountability is exactly what disappears when you skip the understanding step. the git commit line makes it almost legally precise your name is on it whether or not you actually built the mental model behind it.
the speed-versus-safety spectrum you're describing maps well onto what's come up elsewhere in this thread someone earlier was describing near-total automation with guardrails for a B2B product and having their initial fears melt away, and I think the honest reconciliation is exactly what you said: it depends on where the system sits on that spectrum. critical, correctness-first systems justify the slower own everything end. throwaway or low-stakes systems can justify leaning further toward trust.
what I think your comment adds that the article didn't have is the framing that this isn't really a technical decision, it's a values decision made explicit ahead of time we choose to stay on the slower but safer side rather than something that gets discovered by accident when a bug forces the question. deciding your position on the spectrum in advance, for the specific system you're building, seems like the actual skill here, more than any single review habit.
My habit is to review the changes after the AI generates the code, understand whether its processing logic is reasonable, and then test it. Only after it passes all tests will I submit and merge it for release. I feel that by understanding the processing logic, I have essentially participated in the processing myself.
by understanding the processing logic, I have essentially participated in the processing myself that's a good way to put what the whole article was reaching for. the debt isn't in whether AI or a human typed the characters, it's in whether a human actually thought through the logic before it shipped.
your workflow review, understand, test, then merge is basically the loan getting paid off before it's even taken out, rather than after. that ordering matters more than people give it credit for.
I am the Lead Dev/Staff Engineer on an AI Product (for almost an year & half) which, I cannot name since I work in Governance & Compliance. I love the crux of this post. I can relate to so many things.
The biggest problems with AI assisted coding are:
When a customer faces an issue in production, the need for people who understand the system with limited access to logs or the data the customer is using to build something. At that point of time, this debt gets paid in time & stress
The dopamine that people get used to by merging PRs at a rapid pace is not a problem, but, the exponential reliance on QA for validating that the small change which was done is actually the small change that it was supposed to be
Loss of curious junior engineers. When everything's a text or voice note away, then they lose the curiosity. Builders will be rewarded but the no. of builders is way less as we all know it
Scaling is a hard problem when we have to solve it right away. I know the success ratio of any software product is pretty low, but when it needs to scale, it should be ready to scale. That would be such a big bummer for a lot of AI generated stuff out there.
appreciate this genuinely valuable to hear from someone at the staff/lead level in a governance-heavy environment, where the stakes on all four of these are higher than most of us are dealing with.
1 is the one that hits hardest: production incident, limited log access, and the debt comes due in time and stress simultaneously. that's the worst possible moment to discover nobody built the mental model, because you're paying interest and principal at once, under pressure, with less visibility than you'd have in a calm debugging session.
2 is a distinction I hadn't drawn clearly the dopamine of merging fast isn't itself the problem, it's that QA absorbs the cost of verifying small instead of the developer. that's the debt getting quietly transferred to a different team, which probably feels like progress right up until QA becomes the bottleneck everyone complains about.
3 is the one I think about most and have the least good answer for. if curiosity gets outsourced before it's ever exercised, juniors don't get the reps that build the instinct in the first place it's not that they lose a skill, it's that they may never build it. that seems like the highest long-term cost of all four, even though it's the least visible on any quarterly metric.
4 ready to scale vs successful at small scale is a distinction AI-generated code doesn't reliably know to make, because it's optimizing for the immediate request, not for the load profile six months out.
genuinely appreciate the depth here this is a more complete list than what I laid out in the article.
The could I explain this without looking at it again test is exactly the bar I hold myself to before merging anything an agent wrote, and it catches more than people expect. What compounds the debt fastest in my experience is not the code itself, it is the PR description the agent writes to go with it. A clean paragraph that says refactored the validation logic for clarity reads like understanding, so you skim the diff instead of reading it, and the loan quietly gets bigger. The fix that has worked for me is treating the agent's own summary as marketing copy rather than documentation, and reading the diff first before I let myself read what it claims the diff does. Your line count debt schedule is a good rule of thumb, I would just add that the interest rate goes up a lot faster when the summary is more confident than the code deserves.
Treating the agent's own summary as marketing copy rather than documentation that's a genuinely important distinction the article missed entirely. I was worried about the code being the thing that creates false confidence. you're pointing at something upstream of that: the summary shapes how carefully you even read the code in the first place.
refactored the validation logic for clarity reads like a colleague vouching for their own work, except the agent has no stake in whether that description is accurate it's optimizing for a plausible-sounding summary, not an honest one. and a confident, well-written summary is exactly the thing that makes you skim rather than read closely, which is the opposite of what should happen when the source is least accountable.
reading the diff before reading the claimed description is a genuinely simple high-leverage habit it inverts the order most people naturally default to and the order is doing more work than people realize. the interest rate point sharpens the whole metaphor too: it's not just size of the diff that predicts debt, it's the gap between how confident the summary sounds and how much scrutiny the code actually got as a result.
The debt framing works because the repayment date is usually chosen by the bug, not by the developer. I liked that you kept the lesson grounded in ownership rather than turning it into a generic anti-AI take, because the real risk is not that the code looks messy, it is that the mental model never got built and the first production issue becomes the forced catch-up session. Your "could I explain this right now without looking again" rule is a good forcing function for that. Curious whether you have found any lightweight review ritual that keeps the speed benefits of AI drafts without letting that understanding debt quietly compound feature after feature.
The repayment date is usually chosen by the bug, not by the developer that's a sharper version of the point than I actually wrote. stealing that.
on the ritual question honestly the explain it right now rule is still the main one I lean on, but I've started applying it at a slightly different point: right after generation, before I move to the next file, rather than at commit time. by commit time I've often already moved on mentally and the check becomes a formality instead of a real one.
the other small thing that's helped: if I can't explain a piece in under a minute, I don't debug it later I rewrite that specific piece immediately, even if it works. rewriting forces the understanding in a way that re-reading doesn't.
still figuring out if that scales past solo small projects though. curious if you've found something that holds up on a bigger team where the person reviewing isn't always the person who prompted it.
The habit at the end is the important part.....AI-generated code should come with a quick self-check: can I explain what this does, why it’s shaped this way, and what might break if I change it?....If not, the code isn’t really mine yet.
The code isn't really mine yet that phrasing is better than anything I used in the article it captures the ownership piece without needing the whole loan metaphor to get there.
The three-part version of the check you laid out is sharper than my original one too what breaks if I change it catches something can I explain it alone doesn't. you can explain what code does without having thought through its blast radius at all and that's usually where the real damage happens later, not in the explaining part.
That’s a sharp way to frame it......“Can I explain this?” catches surface understanding. “What breaks if I change it?” catches ownership. That second question is where a lot of AI-written code quietly exposes whether you actually understand the system.
Right, and I think that's why can I explain it alone lets people fool themselves so easily. explaining what a function does is often just describing its surface behavior back you can narrate the happy path confidently without ever having thought about what depends on it.
What breaks if I change it forces you to actually model the system around the code not just the code itself. that's a genuinely different and harder question, and I think it's the one that actually predicts whether you'll survive touching it again in six months.
I started asking AI for smaller chunks instead of whole features. It feels slower, but I spend way less time wondering what past me was thinking.
less time wondering what past me was thinking is such an honest way to put it that's usually the tell that a habit is actually working, not just theoretically sound.
smaller chunks make sense as a tradeoff too: each piece is small enough to fully hold in your head while reviewing it, so the understanding actually forms in real time instead of getting deferred to I'll get it later. slower up front, but you're not borrowing against future-you nearly as much.
I like the "small loan" analogy. AI can definitely speed up development, but any time it saves upfront still needs to be paid back through code review, testing, debugging, and long-term maintenance.
I've found AI works best as a productivity tool rather than a replacement for understanding the code. If I can't explain how a generated function works or why a particular approach was chosen, I probably shouldn't merge it into production.
The real value comes from combining AI's speed with human judgment and responsibility.
AI as a productivity tool rather than a replacement for understanding is exactly the line I'd want people to take away from this.
the merge rule you described if you can't explain the function or the approach, don't ship it is basically the practical version of everything the article was trying to say in metaphor form. appreciate you putting it that plainly.
Hey Harsh hope you are doing well ❤️
Harsh, I genuinely loved this perspective. The idea that every AI-generated line of code is a small loan is such a powerful analogy because the real cost isn't paid when the code is written—it's paid later through maintenance, debugging, onboarding new teammates, and understanding decisions months after they're made. AI can dramatically increase our speed, but speed without comprehension quietly turns into technical debt. The developers who will benefit the most from AI won't be the ones generating the most code, but the ones who combine AI's efficiency with solid engineering judgment, clear documentation, and a deep understanding of what they're shipping. This was a thoughtful reminder that sustainable software isn't measured by how quickly we write code, but by how confidently we can maintain and evolve it over time. Beautifully written, Harsh—absolutely loved this! ❤️
Hey I Am doing Well thank you so much for this genuinely 🙂
speed without comprehension quietly turns into technical debt that's a cleaner one-line summary than what I wrote. and I think you're right that the real differentiator going forward isn't who uses AI, it's who combines it with the judgment to know what still needs to be understood versus what can just run.
really appreciate you reading it so closely ❤️
The loan metaphor matches what I measured. I ran two fresh review agents over my entire codebase — not a diff, the whole corpus — when it was about a week old. 47 findings: duplicated logic, drifted docs, patterns that had quietly diverged. Zero of them visible in any single PR, because every PR was locally correct. The debt accumulates between diffs. So now I repay on schedule: a full-corpus pass at every stage boundary, not when it hurts.
The debt accumulates between diffs is the sentence that should've been in the article. that's the actual mechanism I was gesturing at without naming it clearly PR-level review checks correctness at the scope of the PR, which is exactly the scope where drift is invisible by construction. 47 findings, zero visible in any single diff, is about as clean a demonstration of that gap as I've seen.
The review on schedule, not when it hurts" framing is the real upgrade here. most review processes are reactive something breaks, then you go looking. running a full-corpus pass at stage boundaries turns debt repayment into a scheduled maintenance cost instead of an emergency one, which is exactly how the actual financial version of this metaphor is supposed to work.
curious what the 47 findings skewed toward was it mostly duplicated logic from re-solving the same problem across sessions, or more docs comments drifting from what the code actually does? trying to figure out if that ratio changes what the highest-value thing to check first is.
I've experienced this too. AI made me incredibly productive at first, but I realized I was becoming slower at debugging because I hadn't built the mental model behind the code. The worst feeling is opening code you generated a month ago and realizing you understand it as much as if someone else had written it. 😭
You understand it as much as if someone else had written it that's exactly the feeling, and it's a strange kind of alienation nobody warns you about. it's not that the code is bad. it's that your own name is attached to something your brain has no real memory of building.
the debugging-slower part is the piece I think gets missed most often, because it doesn't show up right away. speed at generation time feels like the whole win. the cost only shows up later, in the exact moment you can least afford it staring at your own file, trying to reconstruct a mental model you never built the first time around.
genuinely relate to the 😭 there.
Your framing of AI-generated code as a loan that gathers interest is brilliant. Very nice post Harsh!
Curious about the research you mention in this post pointing to evidence that AI-generated code has a cost. Could you share those links with me? I would love to read more on this.
The title I must admit is brilliant*
appreciate that honestly took a few tries to land on it the loan framing felt right the moment it clicked everything before that felt like it was describing the problem without naming it.
The sentence that stayed with me: the debt does not show up immediately, which is what makes it dangerous. We hit this exactly with a Next.js API layer we were building. The generated route handlers read cleanly on review and the unit tests covered the happy path end to end. What no test ever reached was the error handling code, because AI tends to generate those branches in ways that look complete but have never been exercised under real failure conditions. The first production incident was also the first time anyone traced that code path at all. What approach have you found that specifically surfaces the branches AI generates but your suite almost never exercises?
The first production incident was also the first time anyone traced that code path at all that's the cleanest possible illustration of why the debt is invisible. the happy path gets exercised constantly just by normal usage. the error branches only get exercised by failure, which by definition doesn't happen until it happens.
the closest thing I've found to actually surfacing this: deliberately writing tests that force the failure conditions rather than trusting that error handling looks right on read-through. for a route handler, that means explicitly testing what happens when the upstream call times out, returns malformed data, or returns a valid-but-unexpected shape not just testing that the happy path returns 200. AI-generated error handling often assumes the failure looks like the training data's idea of a typical failure, which isn't the same as your actual upstream's failure modes.
mutation testing is the other thing worth trying if you haven't tools that deliberately introduce small breaks into your code and check whether your test suite actually catches them. it's very good at exposing exactly the gap you're describing: code that reads as covered because a test touches the function, without any test actually exercising the branch that matters.
neither of those would have caught it before the first real failure with certainty, honestly. but they shift the odds meaningfully compared to reviewing the code and trusting that the error handling looks complete.
Great perspective. AI can speed up coding, but understanding the output is what prevents future technical debt. The real skill is balancing AI assistance with engineering judgment.
Thank you Maria balancing AI assistance with engineering judgment is exactly it the tools aren't the problem it's knowing when speed needs to slow down for understanding to catch up.
Great perspective AI speeds up development, but understanding the code is what keeps maintenance costs low. Ownership still matters.
Great analysis! The comparison table is really helpful. I've been exploring similar tools lately.
Great article! You can build a production SaaS for $0/month in 2026. The free tier ecosystem is mature. MonkeyCode (monkeycode-ai.net) is another tool that deserves more attention.
When I use ai in projects I make sure to understand what it is doing, well i'm pretty good at typescript and Rust anyways..
That's honestly the ideal setup strong fundamentals in TypeScript and Rust mean you can actually evaluate what AI hands you instead of just trusting that it compiles. the debt in the article mostly hits people using AI to work in territory they don't already understand well since there's no existing mental model to check the output against.
curious whether that gets harder with Rust specifically though the borrow checker will catch a lot of correctness issues for you, but I'd imagine AI-generated Rust can still be technically valid but not idiomatic which compiles fine and still isn't quite what you'd have written yourself.
Well written! For those exploring free options, Hugging Face models + MonkeyCode (monkeycode-ai.net) gives you a complete AI development stack without any recurring costs.