Submissions are open — put your project in front of the r/startupaccelerator community →
Engineering3 min read

Vibe coding reached production. Here is what breaks first.

AI writes most of the code in a lot of new startups now. The failure modes are consistent, they are boring, and they are entirely avoidable if you know where to look.

The short version

  • The trust boundary breaks first: generated endpoints answer "what?" without ever asking "whose?". Put authorization in the query, not in a branch above it.
  • The second failure is architectural drift — thirty competent implementations that share no conventions, so the debt lives in the absence of a decision.
  • Generated tests assert what the code does, not what the product promised, so they go green and catch nothing that matters.
  • Spend the time AI saved on the three things it is worst at: boundaries, conventions, and tests written from requirements.

Vibe coding stopped being a novelty some time last year. Whole products now ship with most of their lines generated rather than typed, and the honest verdict is that it works — right up until it does not. The interesting question is no longer whether to use it. It is which specific things break, and in what order.

First to break: the trust boundary

Generated code is confident about the happy path and vague about who is allowed to walk it. The pattern repeats across codebases: an endpoint that reads an id from the request and returns the record without ever asking whether the caller owns it. Nothing in the diff looks wrong. The test passes, because the test was generated from the same assumption.

  • Every handler that takes an id must answer "whose?" before it answers "what?".
  • Authorization belongs in the query, not in a branch above it — WHERE user_id = ? cannot be forgotten the way an if-statement can.
  • Ask for the failure cases explicitly. Models write the path you described; the paths you did not describe simply do not exist.
The trade the industry keeps re-learning: velocity borrowed at the start is repaid, with interest, as debugging time later.

Second: the architecture nobody chose

Ask for a feature and you get a competent implementation of that feature. Ask thirty times and you get thirty competent implementations that share no conventions. This is how a small product ends up with three date formats, two HTTP clients, and a queue nobody remembers introducing. The debt is not in any one file — it is in the absence of a decision.

Speed purchased today arrives as a maintenance invoice tomorrow. The invoice is payable in debugging hours, and it is not optional.

Third: the test suite that agrees with you

Generated tests tend to assert what the code does rather than what the product requires. They go green, coverage looks respectable, and none of them would notice a regression that matters. A test written from a requirement can fail usefully; a test written from an implementation can only fail annoyingly.

None of this is an argument against generating code. It is an argument for spending the time you saved on the three things generation is worst at: deciding the boundaries, choosing the conventions, and writing the tests that encode what you actually promised users.

Accelerator AI

Put this article to work

Ask it a question, or turn it into a to-do list for your own project. Both answer strictly from this article — nothing invented.

Answers are generated from this article only and are a working draft, not advice.

Questions this answers

Is AI-generated code safe to ship to production?

It is safe to ship once reviewed for the failure modes it reliably has. Industry reporting puts vulnerabilities in a large share of AI-generated code, and the pattern is consistent: missing authorization on reads, inconsistent conventions across features, and tests generated from the implementation rather than the requirement. None of that is an argument against generating code — it is an argument for reviewing the specific things generation is worst at.

What is the most common security flaw in vibe-coded apps?

Missing object-level authorization. An endpoint reads an id from the request and returns the record without checking whether the caller owns it. It looks correct in the diff and the generated test passes, because the test was written from the same assumption. The durable fix is to scope the query itself — WHERE user_id = ? cannot be forgotten the way an if-statement can.

How do you avoid technical debt when AI writes most of the code?

Decide the conventions before you generate against them, and review every diff as if a fast contractor wrote it who has never met your customers. Debt from generated code accumulates as inconsistency — several date formats, duplicate HTTP clients, an unplanned queue — rather than as bad individual files.

aivibe codingsecuritycode quality
Found this useful? Send it to a founder who needs it.

Building something?

Put it in front of founders who read this — free listing, community-voted, reviewed before it goes live.

Submit your project →