The shift
Something changed in the last two years. Not gradually, not incrementally, the way most things in software change. It was sudden enough that teams who weren't paying attention found themselves six months behind before they understood what had happened.
AI coding tools became genuinely useful. Not as novelties. Not as party tricks. As real, daily-use instruments that measurably change what a small, disciplined team can output.
I run an engineering team. I was sceptical for longer than I should have been, which I'll admit because I think the admission is more useful to you than the pretence of early conviction. What changed my mind was not a demo. It was watching the work.
What it actually is
The first thing to settle, before any of the practical questions, is what you are actually dealing with. Because the category error most engineers make is treating AI as either magic or fraud, and both postures produce the same outcome: you don't use it well.
It is a very fast, very well-read engineer who has never run anything in production. That framing matters. It has read more code than any human has or will. It knows the shape of most problems you will bring to it. It can hold a lot of context and return a coherent answer faster than you can type the question.
What it cannot do is care about your system. It does not know that this particular endpoint gets hit fifty thousand times a day. It does not know that the previous engineer made a subtle indexing decision here for a reason that is not in the code. It does not know what your product promises its users, or what breaks trust with them when something goes wrong.
You know those things. That is the asymmetry you have to keep in mind.
The pilot does not hand the controls to the co-pilot and go to sleep. The co-pilot is there so the pilot can think more clearly.
Treating it like a junior dev
This is the mental model I have landed on, and I have found it more durable than any other: treat the AI like a talented junior developer who you are responsible for.
A good junior can move fast on well-defined tasks. They are eager. They will produce something for almost every brief you give them. They are not slacking; they are genuinely trying. But they have not yet developed the instinct for what matters, and they have not yet been burned enough times to know where the traps are.
You do not hand a junior the keys to a payments migration and walk away. You scope the task tightly. You review the output before it ships. You catch the thing they missed not because they are careless but because they lack the scar tissue.
Same with the AI. Give it a well-defined task. Read what it gives you. Understand it before you commit it. If you cannot explain what the code does to another engineer, you have not finished the job yet.
The danger is not that AI produces bad code. It is that it produces code that looks correct, reads cleanly, and has a subtle flaw that only reveals itself under conditions the AI never considered because you never told it to. That flaw is your responsibility, not the tool's.
✦ Tip
The review is not optional.
If you are merging AI-generated code you have not read, you are not going faster. You are borrowing time you will pay back later, at interest, usually in production.
Where it earns its keep
There are categories of work where AI is genuinely transformative. I want to be specific about them because vague enthusiasm is not useful.
Boilerplate and scaffolding. Serializers, migrations, CRUD endpoints, test fixtures, type definitions. Work that is correct-by-pattern. The AI knows the pattern. Let it run.
First drafts of unfamiliar territory. When you are working in a codebase area you do not know well, or a library you have not used before, the AI can produce a working skeleton faster than you can read the docs. You still read the docs. But you start with something real rather than a blank file.
Writing tests. Describe the behaviour you want verified and the AI will generate a test structure. You still need to think about what is worth testing and what the edge cases actually are. But it eliminates the friction of getting started, which is often the only friction preventing you from writing tests at all.
Explaining code you didn't write. Paste a function, ask what it does, ask where it could break. This is a legitimate and underrated use. It is faster than reading alone and often catches things you would have missed in a first pass.
Rubber ducking at scale. Describing a problem to the AI and reading its response often clarifies your own thinking, even when the response is wrong. The act of formulating the question is half the work. The AI just makes you do it faster.
Where it will mislead you
Equally important, because I think this is less discussed, are the places where relying on AI will quietly degrade the quality of your work.
Architecture. The AI will give you an architecture. It will be reasonable. It will not be yours. Architecture is the accumulation of decisions made by people who understand the specific constraints, the team's strengths, the product's trajectory. The AI does not have that. Use it to pressure-test a design you have already thought through. Do not use it to produce the design in the first place.
Performance-critical paths. The AI optimises for correctness and readability. It does not know that this query runs against a table with eighty million rows, or that this endpoint is called on every page load. You do. The AI will not lie to you here, it just doesn't have the information to make the right call. You have to carry that context yourself.
Security boundaries. Authentication, authorisation, data isolation. The AI will write code that looks correct. Security flaws are rarely obvious. They live in the gap between what the code does and what the attacker assumes it doesn't do. That gap requires a human who is specifically thinking about adversarial conditions, not just happy paths.
Domain logic that is bespoke to your product. If your business has rules that are not in any textbook or open-source repo, the AI does not know them. You have to bring that knowledge to the session, or you will get code that is logically consistent but wrong for your product.
⚠ Gotcha
Confident and wrong is the failure mode.
The AI will not usually say it doesn't know. It will produce something plausible. The more domain-specific your problem, the more important it is that you verify rather than trust.
The real question
The engineers on my team who use AI best are not the ones who prompt the most. They are the ones who have developed a clear sense of when to reach for it and when to think first. They use it to accelerate work they already understand. They do not use it to avoid understanding work they should.
That distinction is harder to maintain than it sounds. It requires a kind of discipline that is not about the tool. It is about knowing what you are responsible for and refusing to outsource that responsibility, even when outsourcing it is fast and the result looks clean.
The engineers who worry me are the ones who cannot read a piece of code they generated and explain every line. Not because AI is dangerous, but because the inability to explain your own code is dangerous, and AI makes it easier than it used to be to ship code you do not understand.
Stay the pilot. Use the tool. Review the output. Know your system better than anything you could ever prompt.
The ones who do that will be better engineers in two years than they are now. The ones who don't will have shipped a lot of code they cannot debug when it matters.
