TL;DR

Vibe coding means describing what you want in plain English and letting an AI write the code without reading much of it. For throwaway tools, prototypes, and small self-contained apps, it’s genuinely great. It falls apart the moment the code has to survive real users, real data, and a second developer. I’ve shipped every mini-app on this site by vibe coding it. I’ve also watched it hand me an admin panel with no auth and a database query wide open to injection. My verdict: use it as a fast first draft, never as a shipping process, and read the security-sensitive parts yourself.

Adoption and security figures below last verified: September 25, 2026.

FactValueSourceVerified
AI code introducing a security flaw45% of samples (reported)Veracode GenAI Code Security Report, Jul 2025Sep 25, 2026
Java security failure rate72% (reported)Veracode, Jul 2025Sep 25, 2026
YC W2025 startups with 95% AI-written code25% (reported)Y Combinator, Mar 2025Sep 25, 2026
Measured speed change from AI tools−19% (slower, reported)METR, Jul 2025Sep 25, 2026

What vibe coding actually means

The term comes from Andrej Karpathy, who posted on February 2, 2025: “There’s a new kind of coding I call ‘vibe coding’, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists.” He was describing a specific mode: you talk to the model, accept what it writes, barely look at the diff, and nudge it when the app misbehaves. In AI-assisted coding you still read every suggestion. Vibe coding is the version where you stop reading.

That distinction gets lost constantly, so let me be blunt. If you autocomplete a function and then review it, you’re doing AI-assisted coding. If you paste a stack trace and apply the fix once you understand it, same thing. Vibe coding is the narrower case where the code is a black box you steer by feel. Karpathy meant it half as a joke about weekend projects. Plenty of people took it as a software methodology, and the trouble grows out of that gap.

By 2026 the practice is everywhere. Y Combinator said a quarter of its Winter 2025 batch had codebases that were 95% AI-generated. Gartner has forecast that 60% of all new code will be AI-generated by the end of 2026 (a projection, not a measurement, though the direction isn’t in doubt). The interesting question in 2026 is what happens to all that code afterward.

My setup: every mini-app on this site was vibe coded

I run a small collection of apps off this blog: little single-purpose tools I build in a Claude session and ship the same day. Every one was vibe coded in the strict sense. I described the tool, took the HTML the model produced, glanced at it, and pushed it live. No test suite, no review, no second pair of eyes. For that kind of work it’s close to magic. An idea at breakfast is a live URL by lunch.

Here’s what the launch tweets leave out, though. The first time I vibe coded something with a backend, a form that wrote to a database, the model gave me a route that looked completely fine and was completely broken. It concatenated user input straight into a SQL string. It passed every test I threw at it, because I wasn’t attacking my own form. If it had been anything other than a toy, it would have been a data breach with my name on it.

My experience splits cleanly in two. When the blast radius is zero, vibe coding is the best tool I’ve ever used. When the blast radius is real, it’s a loaded gun pointed wherever the model was feeling that day.

Where vibe coding genuinely wins

Let me give it full credit, because it earns it.

Throwaway tooling. A script to rename 400 files, a one-off data cleanup, a quick chart from a messy CSV. This code runs once and dies. Correctness is easy to eyeball from the output, and nobody inherits it. Vibe coding here is pure speed with no downside.

Prototypes and demos. When the goal is to find out whether an idea feels right, the fastest path to a clickable thing wins. I’ve vibe coded three or four prototypes that told me an idea was bad before I’d have finished setting up the project by hand. That’s genuinely valuable: killing a bad idea in an afternoon instead of a week.

Self-contained frontends. A calculator, a visualizer, a landing page. No shared state, no auth, no data anyone depends on. The mini-apps I ship fit exactly here. If the worst-case failure is “the layout looks weird on mobile,” ship it and move on.

Learning an unfamiliar API. Ask the model to wire up something you’ve never touched, watch what it does, then read the parts you don’t recognize. This one’s a gray area. It only stays safe if you actually do the reading afterward, at which point it stops being vibe coding and becomes learning.

The pattern across all four: the code is small, the failure is cheap, and you can judge correctness from the outside. Break any of those conditions and the math changes.

Where it breaks: the production wall

Production is a different environment with different rules, and vibe-coded code breaks there in ways that are boringly predictable once you’ve seen them a few times.

Security is the big one. Veracode ran 80-plus coding tasks across more than 100 language models in mid-2025 and found that 45% of the generated code introduced an OWASP Top 10 vulnerability. These weren’t exotic bugs; they were the standard flaws every security course covers. Java was worst at a reported 72% failure rate; even Python, the best of the four languages tested, failed 38% of the time. Cross-site scripting was especially grim: the models failed to defend against it in 86% of relevant samples. And the finding that should end the “it’ll get better with bigger models” argument: security performance stayed flat across model sizes. The models got better at writing code that runs and no better at writing code that’s safe.

Here’s the kind of thing that shows up. This is close to what I got the first time I asked for a “simple user lookup endpoint”:

# What the model handed me: looks fine, isn't
from flask import Flask, request
import sqlite3

app = Flask(__name__)

@app.route("/user")
def get_user():
    user_id = request.args.get("id")
    conn = sqlite3.connect("app.db")
    cur = conn.cursor()
    # string-formatted SQL: classic injection hole
    cur.execute(f"SELECT name, email FROM users WHERE id = {user_id}")
    return {"user": cur.fetchone()}

Hit that with ?id=0 OR 1=1 and it hands back the first user in the table; a little more effort and it dumps all of them. The fix is trivial once you notice it, and noticing is exactly the step vibe coding skips:

@app.route("/user")
def get_user():
    user_id = request.args.get("id", type=int)  # reject non-integers
    if user_id is None:
        return {"error": "invalid id"}, 400
    conn = sqlite3.connect("app.db")
    cur = conn.cursor()
    cur.execute("SELECT name, email FROM users WHERE id = ?", (user_id,))  # parameterized
    row = cur.fetchone()
    return {"user": row} if row else ({"error": "not found"}, 404)

The model can write the second version. It just doesn’t, unless you ask, because the first one satisfies the prompt and the vibe. It’s the same pattern that runs through every honest look at AI coding tools: the output looks plausible and quietly skips the guardrail you never mentioned.

Unauditable business logic. When you never read the code, the rules of your application live somewhere you can’t see. Six weeks later a customer asks why they got charged twice, and the answer is buried in 2,000 lines nobody has ever read, written in whatever style the model felt like across a dozen sessions. CodeRabbit’s December 2025 analysis of 470 open-source pull requests found AI co-authored code carried 1.7 times more issues per PR and up to 2.74 times more security vulnerabilities than human-written code. That kind of bug stays invisible until a customer or an auditor trips over it.

The handoff tax. Vibe-coded code has no author. When a teammate opens it, or when you open it three months later, there’s no mental model to recover, because there never was one. The conventions drift from session to session, so you can’t even lean on consistency to find your way around. I once inherited a roughly 900-line vibe-coded file and spent longer undertanding it than rewriting it would have taken. The hidden cost of code nobody read is that understanding it later always starts from zero.

Environment assumptions. Vibe-coded apps love to hardcode a local path, assume a dev-only config, or bake in an API key that works on your laptop and nowhere else. The demo runs, the deploy doesn’t, and because you never read the code, the debugging session starts from zero.

The productivity paradox

The seductive claim is that vibe coding makes you faster. The best data we have says the opposite for experienced developers on real codebases. METR ran a controlled study in July 2025 where seasoned open-source developers worked with and without AI tools. They believed the AI made them about 20% faster. Measured, they were 19% slower. The gap between how fast it feels and how fast it actually goes is where vibe coding fools you. I wrote up why it happens in the AI coding productivity paradox, and it maps straight onto vibe coding. Generating a draft is fast. Reading, correcting, and re-steering a draft you didn’t write is slow, and the slowness hides behind the dopamine of watching code appear.

For greenfield toy projects the speed is real, because there’s nothing to reconcile the output against. For anything with existing structure, the reconciliation tax eats the gains.

45%
AI code with a security flaw (reported)
−19%
Measured speed change (reported)
2.74×
More vulns vs human code (reported)

How I actually vibe code now

I didn’t stop. I changed where the line sits. The rule I settled on: vibe code the draft, then switch modes and read everything that touches auth, money, user input, or the database. Everything else can stay a black box until it misbehaves.

Concretely, I give the model a standing set of constraints instead of trusting the defaults. A short rules file at the project root does most of the work:

# Project rules for the AI

- Parameterize every database query. Never format SQL with f-strings or concatenation.
- Validate and type-coerce all request input before use. Reject, don't coerce silently.
- No secrets in source. Read from environment variables; add a .env.example.
- No hardcoded paths or localhost URLs. Use config with sane defaults.
- Every endpoint that reads user data must check authorization first.
- When you add a dependency, say why in one line.

That doesn’t make it engineering, but it puts a floor under the process. The model still writes code I don’t read; the categories most likely to hurt me just start from a defensible default. For anything genuinely production-bound I go further and lean on real guardrails that survive contact with agents, since a rules file only nudges the model and never actually stops it.

Before anything vibe-coded goes near real users, I run the same five-minute pass every time: grep for string-formatted SQL, confirm every route that returns user data checks auth, search the tree for hardcoded keys and localhost URLs, and skim the error handling for silent except blocks. It catches most of what the Veracode numbers predict, and it takes a fraction of the time the model saved me on the first draft. The point isn’t to review everything. It’s to review the four categories that turn a bug into an incident.

The other habit: I pick the tool by the stakes. For a mini-app I’ll vibe code in whatever’s fastest. For anything real I use a setup where I can see and stage the diffs. I dug into those tradeoffs in my Cursor vs Copilot real-cost breakdown; the short version is that which tool you pick counts for far less than whether you’re reading the security-sensitive parts.

Who should vibe code, and who should not

Vibe code freely if: you’re prototyping, building throwaway tools, making self-contained frontends, or learning an API you’ll read afterward. The failure is cheap and you can judge the result from the outside.

Vibe code carefully if: you’re a solo founder shipping an MVP. It’ll get you to a demo fast. Budget real time to read the auth, payment, and data-handling code before a single real user touches it, and treat the AI’s output there as a first draft from a talented intern nobody ever told about security.

Don’t vibe code if: you’re working in a shared codebase, handling regulated data, or writing anything where a silent bug becomes someone else’s incident at 3 a.m. Non-developers are now a reported majority of vibe coding users, and that’s exactly the group least equipped to spot the injection hole in the code above. If you can’t read the output, you can’t ship it to production.

FAQ

What is vibe coding?

Vibe coding is describing what you want to an AI in plain language and accepting the code it writes without reading it closely, steering the app by how it behaves rather than by reviewing the source. Andrej Karpathy coined the term in February 2025. It’s different from AI-assisted coding, where you review each suggestion.

Is vibe coding dead?

No, but the hype phase is over. In 2026 it has settled into a real, narrow role: fast drafts, prototypes, and small self-contained apps. What died is the idea that you can vibe code production software without ever reading it. The practice is more popular than ever; the fantasy around it is what faded.

Is vibe coding good or bad?

Both, depending on the stakes. It’s genuinely good for low-risk code where failure is cheap and you can judge correctness from the outside. It’s bad for anything handling real users, money, or data, because AI-generated code introduces standard security flaws at a high rate, and the whole point of vibe coding is that nobody reads it.

Why does vibe-coded code break in production?

Because production has constraints the model was never told about: real inputs from hostile users, secrets that can’t live in source, environment configs that differ from your laptop, and business rules someone will need to audit later. Veracode found 45% of AI-generated code carries an OWASP Top 10 vulnerability, and vibe coding skips the review step that would catch it.

Can you build a real production app by vibe coding?

You can get to a working prototype fast, but shipping it to real users safely means switching out of vibe mode and reading the security-sensitive parts yourself. The teams doing this well let AI draft and keep humans reviewing the code that touches auth, payments, and data.

Sources

Bottom line

Vibe coding is the best fast-draft tool I’ve ever used and the worst shipping process I can imagine, and both are true at once. The trick is knowing which situation you’re in before you start, and being honest about it. If the code will run once, or nobody inherits it, or the worst failure is cosmetic, give in to the vibes completely. If real people, real money, or real data are on the other end, the vibes get you a first draft and nothing more. Draft with vibes; ship with eyes open.