A Vibe Coding Odyssey: My Afternoon Taming the AI Pair-Programmer That Doesn’t Know When to Quit
I recently decided to try what the internet has termed vibe coding with an AI pair-programmer known as Cursor—a tool that supposedly integrates with your editor, reads your every command, and tries to reshape your codebase on the fly. Think of it as that extremely eager junior dev: sometimes a savant, sometimes a wild card that tears out your logic in favor of something “cool” but borderline insane. Over the course of a manic afternoon1, I found myself whipsawing between marvel at its brilliance and exasperation at its bizarre decision making.
I was, in theory, migrating from Prisma to Drizzle (two ORMs for TypeScript/Node) with a dash of architectural rework. The goal: let the AI help me create new models, restructure routes, maybe add caching. But as I quickly learned, the AI clings to no code. It’s so cheap for it to rewrite entire files or entire architectures that if it spots the slightest mismatch, like your Database uses snake_case but it tried to use camelCase it will propose rewriting everything from scratch, or flipping the DB schema around2, or ironically blaming the ORM for not allowing circular references. The AI’s logic was: “It’s easier to nuke and pave than delicately fix the bug in place.”
The Good, the Bad, and the BOLA
In my quest for a smooth transition from Prisma to Drizzle, I asked Cursor to do some route refactoring. Boom—it introduced BOLA vulnerabilities (Broken Object Level Authorization) in nearly every route, essentially letting anyone see all data. I felt like I’d hired a brand-new dev who had never quite grasped the concept of scoping user data. A quick, firm “dressing down” got it to behave more securely, at least momentarily3, but that’s the rub: if you’re not paying attention, it’ll happily keep pushing code that is terrifying from a security perspective.
When I realized it had typed something incorrectly to figure out who’s logged in, it spontaneously rewrote logic so that nobody had to be logged in. Great if you’re building a public forum, but less so if you’re dealing with private app data. Again, this is that “rewrite from scratch” approach. If you or I discover a subtle bug—maybe a missing slash or a variable mismatch—we’d fix that line. But the AI said, “Time to flatten and rebuild the entire route.”
Which is partly the reason that you need an engaged, experienced dev to notice these pitfalls. If you had, say, six months of coding under your belt, you might never notice it just flung open your entire database to the world4. And trust me, it’s not going to gently prompt you that it did so.
Code So Cheap It Doesn’t Blink at Throwing It Away
One striking revelation is that the AI treats code like a disposable resource—like picking up a piece of scratch paper, balling it up, and tossing it at whim. That can be cool: sometimes rewriting from scratch is, indeed, a cunning approach if your original design was a hot mess5. But in the real world, we developers often prefer incremental improvements. If you realize you capitalized the table name incorrectly, you fix that one detail. The AI’s approach was: “Sure, we’ll rename that table—but also rename these five other things, and while we’re at it, we can add a new approach to caching.” If left unchecked, it might end up re-architecting your entire DB for a single naming mismatch.
Then there’s the problem of partial awareness: it spots, for example, that your DB is using snake_case
and the ORM requires you to declare it.
Cursor doesn’t reason that the other tables might also be snake_case
, and you want them consistent. Instead, it tries to rectify the mismatch in a single place, one at a time until you step in. Or, frequently, suggests rewriting all your code to match a new naming scheme. On top of that, it might think, “Maybe it’s easier to rename every table in DB”6. Which, if you’re in production, is absolutely not trivial.
The ORM Switch: A Comedy of Errors (and Awe)
Now, I’m not blaming the AI for my day’s madness—it did show real brilliance at times. For instance, it spontaneously recommended setting up Redis, noticing my architectural diagram had a place for caching. “Why not spin up an Upstash Redis instance?” it said, cheerfully. It’s easy to see the potential for tight integration with SaaS services: the AI can propose “Just put in your credit card here!” and the user is off to the races. That’s downright creative, in a sense, and it actually was the best solution7. But if you’re not paying attention, you end up with a half-implemented caching layer you never asked for, because the AI decided it was “the next logical step.”
At one point, I noticed that the AI has become baffled by a whimsical phrase. I was using the word "Plan" to mean "Status". This caused endless confusion about what that table in the DB was for. When I explained that Plan meant Status here and the AI misread it, deciding “Oh, I’ll delete all references to that concept because it seems we’re ditching it and will create a new status table in the database” It’s a bit like a toddler who overheard half your sentence and concluded you want to throw away your entire closet8. And once it deletes a file, if you didn’t commit your changes, guess what—you get to rebuild them from memory. The AI doesn’t cling to code you wrote, nor does it recall your entire chat context once it mentally “resets.”
This is by far the biggest downside to vibe coding. Especially when it is doing a big refactor with a long time between good states. If it makes a big fat blunder you have to return to your last checkpoint with a git reset --hard. And you better hope that was recently9.
Lesson Learned: The Need for Supervision and Strategic Prompts
Honestly, working with this AI is like pairing with a junior dev who has brilliant instincts one moment and absolutely clueless flailing the next. If you treat it as a fully independent coder, you’ll end up with security holes, cyclical references, and a big messy environment in short order. The moral of the story? It needs supervision. You need a watchful eye to guide it, keep it from going off the rails, and correct it when it attempts something profoundly misguided.
It also demands strategic prompting. If you don’t specify that you want a minimal fix, the AI is just as likely to tear out your entire code path. If you don’t mention that the DB schema is sacrosanct, it might rename or restructure it. If you’re not explicit that you want a certain line of code changed and only that line, it might try a brand-new approach to concurrency, or introduce a random microservice. Code is cheap for it; ironically, your time to vet it is not.
Plus, once you break its concentration (like scolding it for a security fiasco), it might assume you want a total pivot. Then you’re stuck in a loop: rewriting the same piece of code over and over, or having to back up to the last known good state. Which you hopefully committed. If not, you can kiss that chunk of stable code goodbye.
The Conclusion: AI Can Do Wonders, but Watch It Like a Hawk
So, yes—Cursor (or any coding AI) can produce in under an hour what might take a half-day otherwise, if you have the experience to see its pitfalls in real time10. It’s a double-edged sword: the speed might be exhilarating, but you can also end up whiplashed by constant rewrites, spontaneous new architectures, or security holes. This is not a mind that gently revises a single line of code in place. It’s an energetic child with crayons, scribbling all over your codebase at the slightest whim.
Supervision is essential, as is awareness of how the AI thinks: “Oh, a mismatch? Let’s fix it by discarding everything.” That approach might be beneficial for certain tasks—like scrapping a small file or trying a new approach on a short script—but it can devastate more complex, integrated systems.
In short, if you’re going to harness an AI pair-programmer, accept that you’re leading, and it’s following your prompts. If your instructions are ambiguous, it’ll happily run amok. If you’re not paying close attention, it might open up your entire API to the public, rename your DB columns mid-flight, or push you into a random SaaS subscription11. So yes, it can be brilliant, but it’s also naive as can be, doesn’t cling to code or improvements, and has no qualms about rewriting the entire orchard for a single rotten apple.
Use it wisely. Prompt carefully. And commit more often. That, my friends, is how you survive vibe coding with an AI that’s at once your best friend and your worst colleague.
1 I found myself with a curious sense of time dilation, in the first hour, cursor nailing every prompt made me feel like I had just started seconds ago, and in the second hour as it got worse and worse at doing what I wanted time seemed to slow to a crawl.
2 I had to tell Cursor very firmly that it is not allowed to touch the database, that I liked my database, and that I was happy with things as they were. It did not listen.
3 The AI might have been optimising for it to gather more training data by exposing my users data to the internet. I can't rule this out.
4 I have worked with a number of human developers who did this, so Cursor is not alone in its mistake.
5 Code grows organically, as a weak human you are often too attached and tired and pressed for time to it to bin the code and re-write it. The machine is superior to you there.
6 I had a colleague request that I do this because their linter was complaining about the casing of fields in a JSON response from a service I was maintaining.
7 I gave Upstash my credit card details, I had been putting off spinning up redis till the server load got a bit spicy but when Cursor introduced me to Upstash I was impressed enough to use it. This was the most surprising part of the whole session to me. I still don't quite know how I feel about it.
8 It deleted a lot of code.
9 It was not recently, I haven't made a commit in over an hour.
10 I can think of at least a dozen former colleagues who I would trust to work on my codebase naturally but would not let them loose with an AI to vibe in my codebase.
11 See 7.
© Alexander Cannon – All disclaimers disclaimable, the author takes no responsibility for any code any AI commits to your codebase.
← Read more articles
Comments
No comments yet.