I Spent 6 Months Vibe Coding. Here’s Why I’ll Never Do It Again.
A developer’s honest account of the moment specs stopped being documentation and became the actual product.
I Spent 6 Months Vibe Coding. Here’s Why I’ll Never Do It Again.
A developer’s honest account of the moment specs stopped being documentation and became the actual product.
I’m going to tell you about the worst bug I ever shipped.
It wasn’t a null pointer exception. It wasn’t a race condition. It was a feature — a fully working, tests-passing, code-reviewed feature — that did exactly what I thought I’d asked for. Not what I needed.
The AI built it faithfully. I just didn’t know how to ask.
That’s the thing nobody talks about with vibe coding. The problem isn’t that AI writes bad code. The problem is that it writes exactly what you describe in the moment, without any memory of everything you said three sessions ago, without any understanding of how this new thing interacts with that old thing, and without any way to push back when your off-the-cuff prompt is missing half the context.
For six months I lived in that world. Chat prompt, generated code, tweak, repeat. I was moving fast. I felt productive. My commit history looked impressive.
Then I hit a wall.
The Wall
It was a Tuesday. I was adding what should have been a simple notification system to a service I’d been building incrementally with AI assistance over several weeks. Four chat sessions, maybe five. Each one started fresh — I’d paste in some context, describe what I needed, review the output, merge it.
The notifications feature took an afternoon. Looked clean. The AI even wrote the tests.
Except three weeks later, a user reported they were getting double-emails on checkout. The kind of bug that’s invisible in a single session but catastrophic in production.
I went back to trace it. What I found wasn’t a logic error in the notification code. It was a context collision — two different sessions had each added their own event listener for the same checkout event, because neither session knew about the other. Both pieces of code were “correct” in isolation. Together they were a disaster.
I had no spec. I had no record of intent. I had chat logs I couldn’t search, comments I hadn’t written, and a growing sense that my codebase was a collection of AI opinions I had agreed to at various points in history.
That was the wall.
What I Was Actually Missing
Here’s what I’ve come to understand: the problem with vibe coding isn’t that AI is bad at writing code. It’s that requirements only exist in your head and in the conversation history, and both of those are terrible places to store them.
Your head forgets. Conversation history fills up. Context windows overflow. And when the AI inevitably makes an assumption — because every coder, human or machine, fills in blanks with assumptions — there’s nothing to check that assumption against.

Vibe Coding vs SDD
What you need is a spec. Not a design doc you write once and forget. Not a README that drifts from reality within a week. A living, version-controlled, machine-readable expression of intent that the AI actually reads before it writes a single line.
That idea has a name now: Spec-Driven Development, or SDD.
What SDD Actually Is (And Isn’t)
I want to be careful here because there’s a lot of hype around this phrase, and not all of it is useful.
SDD is not a return to waterfall. You are not writing a 40-page requirements document before you’re allowed to touch a keyboard. You are not promising your team that the spec is complete and frozen.
SDD is the practice of agreeing on what you’re building before you start building it, encoding that agreement in a file that lives in your repository, and using that file as the actual input to your AI coding agent rather than an improvised chat prompt.
The spec becomes the contract. The AI becomes the contractor. You become the architect.
The difference sounds subtle. The outcome is profound.
My First Real Spec
After the double-email incident, I went looking for tooling. I found two main options: GitHub’s SpecKit and a community project called OpenSpec. I’ll write more about the comparison in the next post — the short version is I chose OpenSpec for its lighter footprint and active community.
Here’s what my first spec looked like. I was adding a user preference center — a fairly involved feature with multiple subsystems. Old me would have described it to the AI in a prompt, got something back, iterated, merged, and moved on.
New me ran npm install -g @fission-ai/openspec and then typed:
/opsx:propose "user preference centre — allow users to set notification frequency, email format, and data export options"
The AI generated a folder: openspec/changes/user-preference-centre/ containing:
proposal.md— a structured description of why we were building this and what it would changespecs/— GIVEN/WHEN/THEN scenarios for each user-facing behaviourdesign.md— a technical approachtasks.md— a checklist of implementation steps
I reviewed it. Changed three things. Approved it.
Then I ran /opsx:apply.
The AI implemented the feature — task by task, reading the spec at each step. Not my frantic prompt from memory. The actual spec.
When it was done, I ran /opsx:verify. It checked the implementation against the spec. Found one gap — a missing error state for the export function. I fixed it.
Then /opsx:archive. The spec merged into the project's source-of-truth document.
The whole thing took two hours. The feature worked first time in staging. And six months later, when someone needed to modify it, they read the spec and understood exactly what the original intention had been.
No double-emails.
Why This Changes Everything
Here’s what I noticed after about a month of working this way.
I stopped dreading the “context window full” message. When you hit the limit with a spec-driven workflow, you don’t start over. You start a new session, hand the agent the spec file, and pick up exactly where you left off. Intent doesn’t live in the chat anymore — it lives in the file.
My code reviews got faster. Instead of reviewers having to reverse-engineer what the code was trying to do, they could read the proposal first. The spec gave them a frame. Reviews that used to take an hour took fifteen minutes.
AI hallucinations dropped noticeably. This surprised me. When the AI has a spec to work against, it has something to check itself against. The structured GIVEN/WHEN/THEN format gives it test cases it can reason about before generating code. The outputs were just… better.
I have an audit trail. Every feature change has a corresponding proposal explaining why it was built the way it was. When something breaks, I know exactly where to look.
The Honest Caveat
I’m not going to pretend SDD has no cost. There is overhead. For a small bug fix, writing a spec is overkill — just fix the bug.
The sweet spot is anything that crosses more than one file, involves more than one session, or touches logic that someone else might need to understand later. For that kind of work, the ten minutes you spend writing a proposal saves you hours on the back end.
The framework I use (OpenSpec) makes this easy enough that I now do it almost reflexively for any feature work. It’s like writing a commit message — slightly annoying in the moment, invaluable six months later.
What’s Next
This is the first post in a three-part series.
Next up: I’m going to walk you through exactly how OpenSpec works under the hood — the three-phase workflow, the delta marker system, and why the 50KB context limit is a feature not a bug. If you want to understand how specs actually get fed to an AI agent, that post is for you.
In part three: The hard part — making SDD work across a microservices architecture with multiple repos and multiple agents running in parallel. Because the dirty secret is that most SDD tutorials assume a single repo. Real enterprise work doesn’t look like that.
Follow me for parts 2 and 3. If any of this resonated — particularly the double-email story — I’d genuinely love to hear your version in the comments. We all have one.
메타데이터
- post_id
- 6fa375246e25
- slug
- i-spent-6-months-vibe-coding-heres-why-i-ll-never-do-it-again-6fa375246e25
- url
- https://medium.com/@apurvsheth/i-spent-6-months-vibe-coding-heres-why-i-ll-never-do-it-again-6fa375246e25
- canonical_url
- https://medium.com/@apurvsheth/i-spent-6-months-vibe-coding-heres-why-i-ll-never-do-it-again-6fa375246e25
- author_url
- https://medium.com/@apurvsheth
- status
- ok
- fetched_at
- 2026-06-13 00:08:42