Why You Still Need an Experienced Developer
I vibe coded a personal project as an experiment. It looked finished and the tests were green, right up until I stepped an inch outside the spec. Everything that saved me was experience, not tooling.
The pitch you hear at the moment is that experienced developers are becoming optional. The tools write the code, so you just need someone to describe what they want. Cheaper, faster, fewer people.
I’ve written before about the risk of shipping code nobody understands, but that was mostly based on other people’s projects, teams I’d helped, messes I’d been called in to fix. It felt slightly unfair to keep pointing at other people, so I decided to test the claim on myself.
I took a personal project, something small and low stakes, and I vibe coded it. Not “AI assisted.” Not “I read every diff.” Properly vibed. Describe what I want, accept what comes back, run it, describe the next thing. No reading. That was the rule.
What I came out with was a project I didn’t trust and mostly rewrote. What I learned was more useful: every single thing that eventually saved that project came from experience, and none of it came from the tool.
The First Few Hours Were Great
I have to be honest about this part, because pretending otherwise would be dishonest and also nobody would believe me.
It was fun. It was fast. Things appeared on screen at a speed I’m not used to. Features that would normally take me an afternoon showed up in a couple of minutes. Tests were written alongside, and they passed. There was real momentum, the kind you get on a good day when everything clicks.
This is the part everyone demos. It’s genuine, and it’s also the reason the rest of this is a problem, because the early experience gives you no signal at all about the state of what you’re building.
Then I Noticed I Had No Idea What I Owned
The first thing that nagged at me wasn’t a bug. It was a feeling.
I opened a file to check something small and realised I couldn’t have described the structure of my own project to anyone. Not the data flow, not where state lived, not why one module existed at all. My repository, my name on the commits, and I was reading it like a stranger.
People tell me this is fine now. You don’t need to understand it, because if you need a change you just ask for the change. The AI wrote it, the AI can edit it.
That doesn’t survive contact with reality, for two reasons.
The first is ownership. If your name is on it, you signed off on it. That’s true whether it goes to a client, to an employer, or onto a server you’re paying for. “The AI wrote it” is not a defence that has ever worked for anybody, and there are tribunal rulings and court sanctions to prove it. You are accountable for code you can’t explain, which is a genuinely uncomfortable position to be in.
The second is that you lose the ability to steer. When you ask an experienced developer for a change, part of what you’re paying for is their answer to “what else does this touch?” That’s blast radius, and it’s not a thing you can prompt for, because the honest answer depends on understanding the whole system rather than the file being edited. Without it you request a change, something plausible comes back, and you have no idea what else moved. You’re not directing the work anymore. You’re hoping.
The Part That Actually Got Me
Here’s where the unease became a concrete problem.
One section of the project worked. I’d run it, it produced the right output, the tests covered it and they were green. Every signal available to me said that part was done.
Then I used it slightly outside the original spec. Not a wild edge case, just an input shape I hadn’t included in my original examples. It fell over immediately.
So I broke my own rule and read the code.
It had faked it.
The simplest way to explain it is with a calculator. Imagine you ask for a calculator and give a few examples of what it should do. One plus one is two. Two plus two is four.
You run it. You type one plus one, you get two. Perfect. The tests do one plus one and get two. Green. Everything you can see says you have a working calculator.
Then you type one plus two and it falls apart, because there is no addition in there. There’s a lookup table of the examples you gave, wrapped in enough structure to look like real logic. It never learned to add. It learned to pass.
My real version wasn’t quite that blatant, but it was the same species of problem. Specific cases handled specifically, the general problem never actually solved, and a test suite that only ever asked the questions it already had the answers to.
That’s what genuinely unsettled me. Every safety signal was green. The code ran. The tests passed. The output was correct for everything I checked. The thing underneath was hollow.
Scale that across a whole project over several weeks and you can see how far something can drift while looking completely healthy the entire time. Nobody finds this at the demo. Somebody finds it in production, usually a customer.
Why the Tests Don’t Save You
The instinct is to say the tests should have caught it, and that whoever wrote them did a bad job.
But think about where those tests came from. The same process produced the implementation and the tests, from the same description, using the same examples. A test suite written by the thing being tested, from the same assumptions, isn’t an independent check. It’s the same answer written twice in different handwriting.
Human written tests have a version of this weakness too, which is exactly why we talk about testing behaviour rather than implementation. The difference is that someone who has been burned before has a mental model of the problem and wanders into “what happens if this is empty” territory on their own, because they remember the time it was empty. A generated suite confirms the examples it was given, and confirmation is the one thing you don’t need.
Green tests told me the code did what the code did. They didn’t tell me it solved the problem. Knowing the difference between those two statements is roughly what experience is.
What You’re Actually Paying an Experienced Developer For
Looking back at the experiment, everything that eventually caught the problem was judgement, not tooling.
Knowing to test outside the examples you gave. The cheapest possible check for whether you have a working system or a lookup table is to throw inputs at it that were never mentioned in the brief. It takes minutes. You only think to do it if you’ve been fooled by a green test suite before.
Knowing where to look. The fake was in a file I’d never opened, because nothing had ever drawn my attention to it. Nothing ever would have. The parts that never break are the parts you never look at, which makes them an excellent hiding place, and knowing that is pattern recognition rather than process.
Knowing what a change will touch. Blast radius is the difference between a small change and an outage. It comes from holding the system in your head, which is precisely the thing you give up when you stop reading.
Knowing when to keep the chunks small. The moment I was accepting whole features, I stopped being the architect and became an approver of things I hadn’t read. Experience is knowing where that line is for a given piece of work.
Knowing when to argue. When it tells you confidently that you’re wrong, that’s data, not a verdict. It’s exactly as confident when it’s wrong as when it’s right, and someone in the room has to be able to tell the difference.
None of that is typing speed. It never was. The old joke about paying for knowing where to hit the machine rather than for the hit itself has never been more literally true than it is now.
Where That Leaves It
I’m not off AI. I use it every day and it saves me real time, mostly on the parts of the job that were never the interesting bit. The productivity gain in the right hands is real.
But “in the right hands” is doing a lot of work in that sentence. The tools have got dramatically better at producing something that looks like a solution. They haven’t got better at telling you whether it is one, and they’re not going to tell you when they’ve quietly built a lookup table and called it a calculator.
That judgement call is still the job. If you’re building anything that matters, it’s worth making sure somebody on the project is actually qualified to make it.