TL;DR
Vibe coding is a great way to turn an idea into a working prototype in an afternoon. But the term is now being applied to every kind of AI-assisted development, including production systems that need real engineering. Using one word for both is how teams end up shipping code nobody understands, can’t debug, and can’t safely change.
In this post you’ll learn:
- What vibe coding originally meant, and how the term drifted
- Where vibe coding is the right tool and where it quietly fails
- The specific failure modes of unreviewed AI-generated code in production
- What AI-assisted engineering looks like day to day
- A short checklist for deciding which mode you’re in
- How to keep your own skills sharp while leaning on AI
The word got bigger than the idea.
When Andrej Karpathy coined “vibe coding” in early 2025, he described a specific mode of working. You talk to an AI, accept whatever it produces, paste error messages back in when things break, and mostly stop reading the code. He framed it as fine for throwaway weekend projects.
That framing got lost fast. Today “vibe coding” is used for everything from a hobbyist building a habit tracker to a team shipping a payments integration with Copilot or Claude open in the next window. Those aren’t the same activity, and they shouldn’t carry the same label or expectations.
The problem isn’t the tool. The problem is that when everything is vibe coding, nobody has to say what standard the code is being held to.
Where vibe coding is the right call
I’m not here to bash it. Vibe coding is good at:
- Prototypes and spikes: You want to know whether an idea is viable before investing in it.
- Internal one-off scripts: A data migration you’ll run once, or a script that renames 400 files.
- Learning and exploration: Seeing how an unfamiliar framework fits together by watching a model scaffold it.
- Throwaway demos: Anything with a known expiry date.
What these share is low blast radius. If the code is wrong, the cost is small and visible. You can delete it and start over.
The moment code has users, data, money, or a maintenance horizon longer than a week, that logic stops holding.
Where it breaks
Here’s what goes wrong when unreviewed generated code reaches production.
- Code that works but isn’t correct: Models are very good at producing code that passes the happy path. Consider this endpoint, which is typical of what you get from a quick prompt:
app.get("/api/invoices/:id", async (req, res) => {
const invoice = await db.query(
`SELECT * FROM invoices WHERE id = ${req.params.id}`
);
res.json(invoice.rows[0]);
});
It runs. It returns data. It also has a SQL injection hole, no authentication check, and no ownership check, so any user can read any invoice by guessing IDs. A demo wouldn’t reveal any of that. A security review would, and so would a person who read the code.
- Invisible architecture decisions: Every generated feature makes choices about error handling, data shape, retries, and where state lives. If you didn’t read the code, you didn’t make those choices, and you don’t know what they are. Six months later, someone has to extend the system and discovers three different patterns for the same problem.
- Debugging without a mental model: When production breaks at 2 a.m., “ask the AI” works only if the AI can see enough context to reason about the failure. Often it can’t. The engineer who has to fix it is now reverse-engineering code they never understood in the first place.
- Dependency and supply chain sprawl: Models happily add packages to solve small problems. They can also suggest libraries that are outdated, unmaintained, or, in rare cases, don’t exist at all, which is an opening for typosquatting. Nobody reviewed the choice because nobody was looking.
- Test theatre: Ask a model to write tests for code it just wrote, and you often get tests that confirm the implementation rather than the requirement. Coverage goes up while confidence shouldn’t.
None of this is unique to AI. Junior developers and rushed contractors produce the same problems. The difference is volume: AI makes it possible to generate unreviewed code faster than any team can review it.
Why the label matters
You might think this is just semantics. It isn’t, because names set expectations.
If a team says “we vibe coded this feature,” that tells reviewers, product managers, and future maintainers that the code is provisional. If the same team says “we built this with AI assistance and engineered it properly,” that signals the code was designed, reviewed, and tested.
When the first label gets applied to code that ships as the second, you get a gap between what people believe the system is and what it actually is. Incident reviews are full of that gap.
Being precise also protects the good version of AI-assisted work. Developers who use these tools carefully shouldn’t get lumped in with “just prompt and pray,” and the term has been dragged in that direction.
What AI-assisted engineering actually looks like
If vibe coding is “accept and move on,” engineering with AI is closer to working with a fast, tireless, occasionally overconfident pair programmer. In practice, that means:
- You own the design: Decide the approach, boundaries, and data model before generating code. Give the model constraints: which patterns to follow, which libraries are allowed, how errors should be handled. A short spec in the prompt beats a long cleanup later.
- You work in small steps: Generate one function or one module, read it, and run it. Large one-shot generations produce large one-shot problems that are hard to review.
- You read every line that ships: Not skim, read. If you can’t explain what a block does, you don’t merge it. This is the single biggest dividing line between the two modes.
- You write or at least specify the tests first: Tests that encode requirements before the implementation exists are far more trustworthy than tests generated afterwards to match it.
- You keep the normal safety rails: Code review, CI, linting, static analysis, dependency scanning, and secret detection all apply to generated code. If anything, they matter more.
- You use the model as a reviewer too: Ask it to find bugs, edge cases, and security issues in your code, or on its own. It’s often good at this, as long as you treat the output as leads to verify rather than verdicts.
Here’s the same invoice endpoint after an engineering pass:
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const id = Number.parseInt(req.params.id, 10);
if (!Number.isInteger(id)) return res.status(400).json({ error: "Invalid id" });
const { rows } = await db.query(
"SELECT * FROM invoices WHERE id = $1 AND owner_id = $2",
[id, req.user.id]
);
if (rows.length === 0) return res.status(404).json({ error: "Not found" });
res.json(rows[0]);
});
A model can help write this. But a human had to know what to ask for and recognize what was missing.
A quick checklist: which mode are you in?
Before you start, answer these honestly:
- Will real users or real data touch this? If yes, it’s engineering.
- Will someone other than me maintain it? If yes, it’s engineering.
- Would a bug cost money, trust, or security? If yes, it’s engineering.
- Will it live longer than a few weeks? If yes, it’s engineering.
- Could I delete it tomorrow without anyone noticing? If yes, vibe away.
Notice that the answer isn’t about which tool you use. You can engineer with the same assistant you’d vibe code with. What changes is your process and your accountability.
It also helps to say the mode out loud in your team. A one-line note in a PR, like “prototype, not reviewed for production,” saves a lot of confusion later. Promoting a prototype to production should be an explicit decision with a rewrite or a full review attached, not something that happens because the demo went well.
Keep your own skills sharp.
One last risk is quieter than the rest. If you never read the code, debug it, or design anything yourself, those skills fade. The developers who will get the most out of AI over the next decade are the ones who can judge its output, and judgment comes from practice.
A few habits help:
- Write the tricky parts yourself now and then, especially in areas you want to stay strong in.
- Before accepting generated code, predict what it will look like, then compare.
- Debug without the assistant sometimes, so you keep your instincts for reading stack traces and tracing state.
- When the model does something unfamiliar, stop and learn why instead of moving on.
Conclusion
Vibe coding is a real and useful technique, and it deserves to keep its original meaning: fast, loose, disposable exploration where correctness isn’t the point. Everything else that involves AI and ships to users is software engineering, with all the responsibility that implies.
Use the right word, and you get the right behavior. Prototype freely, label it honestly, and when the work matters, slow down, read the code, and engineer it. The model can write the lines, but you’re still the one on call when they fail.
How do you draw the line on your team? I’d like to hear from you in the comments.
Top comments (3)
The line that stuck with me is “when everything is vibe coding, nobody has to say what standard the code is being held to.” The real problem isn’t the tool, it’s that the word has stopped telling anyone what level of scrutiny to expect.
The invoice endpoint before/after example works well because the first version runs. Nothing fails in a demo, so nothing prompts anyone to look closer. That’s what makes unreviewed generated code risky: it looks finished.
I also like the idea of putting “prototype, not reviewed for production” in the PR description. It’s a tiny habit, but it makes the gap visible. In my experience, prototypes become production code mostly because nobody ever made an explicit decision to promote them.
One thing I’d add to the checklist: “Will it handle anyone’s personal or payment data?” That probably deserves its own question, since it raises the stakes even when the user count is tiny.
On my team, we draw the line at ownership: if someone has to be on call for it, it gets read line by line, whatever tool wrote it. How do others handle a prototype that gets promoted after a successful demo? Do you rewrite it, or do a full review of what’s there?
Thanks for reading this closely, and for pulling out that line. It’s the one I’d defend if I had to cut the post down to a single sentence. The word has stopped telling people what level of scrutiny to expect, and that’s the actual damage.
You’re right that “it looks finished” is the real danger. The invoice endpoint passes a demo, and a passing demo is exactly what takes away the reason to look closer. I’d add that reviewers tend to relax once they’ve seen it work, which makes the polished version harder to challenge than a rough one.
Your point about personal or payment data deserves its own checklist item, and I’m going to add it. It changes the stakes regardless of user count, because a prototype with ten users and real card details is still a production incident waiting to happen.
I like your ownership rule too. “If someone has to be on call for it, it gets read line by line” is much easier to apply than any judgment about how serious the code feels, and it sidesteps arguments over what counts as a prototype.
On your question, I lean toward a rewrite when the prototype’s structure is the problem, and a full review when the structure is sound but the details are untested. The deciding factor is usually whether the demo’s shortcuts (hardcoded config, no error paths, no auth) are scattered everywhere or contained in a few places. If they’re everywhere, reviewing line by line costs more than starting clean with the prototype as a spec.
Curious what others do here, especially whether anyone has a rule for when a prototype is allowed to be promoted at all.
The line about nobody having to say what standard the code is held to is the best part. The word “vibe coding” has become a way to skip that conversation.
The invoice endpoint example works because the first version runs fine. Nothing breaks in a demo, so nothing makes anyone look closer.
The “prototype, not reviewed for production” note in the PR description is a small habit with real payoff. I’d add one checklist question: “Will it touch personal or payment data?” That raises the stakes even with a handful of users.
On our team, if someone has to be on call for it, it gets read line by line, whatever tool wrote it. How do you all handle a prototype that gets promoted after a good demo: rewrite or full review?