I work with leaders and teams on clarity, capability, and momentum. Work with me →
Vibe coding produces code. Engineering produces systems. The gap between those two things is where production failures live.
This is not an argument against AI. It is an argument for engineering.
A model can generate a login system in seconds. It will not ask if emails must be unique. That single missing requirement can collapse the system. LLMs cannot see the category of questions that keep software safe.
Vibe coding gives you code. It gives you output. It gives you momentum.
What it does not give you is coherence.
Before any code exists, engineers make the decisions that keep systems safe.
| Topic | Description |
|---|---|
| Problem framing | Define the problem, the user, the constraints, and the intended outcome. |
| Requirements engineering | Elicit behaviours, invariants, edge cases, and acceptance criteria. |
| System modelling | State models, data flows, sequence diagrams, causal reasoning. |
| Architectural design | Boundaries, responsibilities, interfaces, failure modes, trade‑offs. |
| Non‑functional requirement definition | Performance, reliability, security, compliance, operability, cost. |
| Risk identification | Unknowns, dependencies, failure points, mitigations. |
| Interface and contract design | Define APIs, schemas, and behavioural guarantees. |
| Planning and sequencing | Break work into coherent, deliverable units. |
When engineers write code, they are not just typing. They are:
Most of this happens before a single line of code exists. This is the work that keeps systems coherent.
These parts of the engineering discipline are skipped by LLMs.
| Area | What engineers decide | What LLMs generate |
|---|---|---|
| Invariants | What must always be true | Code that assumes everything is fine |
| Identity & Uniqueness | What makes an entity "the same thing" | Code that treats everything as interchangeable |
| Constraints | What the system must never allow | Code that violates boundaries without noticing |
| Failure Modes | How the system behaves under stress | Code that only works in the happy path |
| Coupling & Sequencing | What depends on what, and in which order | Code that ignores ordering entirely |
| State & Transitions | How state changes and what triggers it | Code that mutates state without rules |
| Interfaces & Contracts | What each part promises to the rest | Code that exposes whatever the model invented |
| Boundaries | What the system does not do | Code that expands until it breaks |
| Error Handling | How the system recovers | Code that collapses on the first unexpected input |
These are not abstractions. They are the decisions LLMs never ask about.
This is why systems fail even when the generated code looks correct.
This matters because a system relies on:
None of these exist in the model's internal world.
AI‑generated code stalls because the engineering decisions were never made.
When such decisions are missing:
Confidence collapses long before the system does. These decisions always reappear later under pressure.
The system is not the code you generate. It is the environment the code runs within.
Given a simple prompt:
write python to "Add user accounts to a website so people can log in."
The model generated a small, working Flask and SQLite example. That is acceptable for a demo but it did not ask about these five requirements:
If emails are not unique, two people can sign up with the same email address. If they are logged in at the same time, user login identity is ambiguous. The system cannot tell the difference between them.
When a user logs in with a repeated email address, the check of that user’s registration from the database will always contain multiple values. Any code built to check for a registered user will now have to safely handle the possibility of multiple results.
The lack of unique‑email consideration means that if a user with a repeated email resets their password, the vibe‑coded implementation will reset the password for all users who share the same email. This is not survivable in production. And if one user deletes their account, multiple accounts will be deleted.
No production system can tolerate this.
Vibe coding assumes the AI is "intelligent" in the way an engineer is intelligent. If that were true, missing requirements, ambiguous rules, and hidden constraints would be caught automatically.
But LLMs do none of this. They do not reason about your system. They do not build a model of your domain. They do not track consequences or protect invariants. They produce text that looks like an answer without doing any of the thinking an engineer does before writing code.
Because the generated code solves the immediate problem, people assume the necessary thinking has been done. They assume the system is coherent because the file runs. They assume intelligence where there is only pattern continuation.
Vibe coding fails in production because the missing decisions reappear later as failures, inconsistencies, and fragility. The model cannot see the category of things that needed to be asked. The human assumed the model had seen them.
Before generating any code, decide:
LLMs generate code. They do not make engineering decisions. That work remains.
Vibe coding gets you a demo. Engineering gets you a system that survives contact with reality.
Read next: The Big AI Gains Come From Teams, Not Individuals
AI makes individuals faster, but the real gains are between groups of people.
If this was useful, you can get more pieces like it in the Phroneses newsletter.
I work with leaders and teams on clarity, capability, and momentum. Work with me →