Table of Contents
Listen to article
When AI coding assistants first entered our workflow, they felt like magic. With tools like Windsurf, Cursor, and GitHub Copilot, we could feed in specifications and get back working code in minutes. For a small team like ours — two developers and a team lead — that speed was a game changer. Our app needed to integrate with client systems, with each module exposing APIs both to the client and to other modules. That meant correctness and consistency across APIs were critical.
We had a structured documentation process: project overviews, domain breakdowns, per-feature descriptions, task breakdowns, and work logs. In theory, this gave AI everything it needed to generate faithful, high-quality code. In practice, vibe coding — leaning too heavily on AI and trusting what “felt right” in the moment — led us into traps. The AI often produced redundant code, drifted from scope, or generated modules that worked fine in isolation but failed at integration.
Through trial, error, and plenty of cleanup, we learned five key lessons that transformed how we work with AI. Here they are.
Lesson 1: Generate and Review in Smaller Increments
Early on, we handed the AI entire feature descriptions and asked it to “generate the module.” The result looked impressive but hid problems: redundant logic, missing spec requirements, and APIs that didn’t connect correctly with sibling modules. Cleaning this up took longer than writing smaller pieces directly.
Now we follow a simple rule: if the diff feels too big to review, it was too big to generate in the first place. Smaller increments lead to cleaner code, faster reviews, and fewer integration surprises. Granularity is key. Even within a single feature it is best to follow your own development logic, and, instead of generating it in a single go, just think what you would do next and request AI to do that first, and so on every step of the way.
Lesson 2: Write Unit Tests from Specifications, Not the Code You Just Wrote
When we wrote tests based on AI-generated code, all we were testing was whether the AI’s version of reality complied. That failed us badly. For example, an endpoint for loan origination created loan records correctly but skipped mandatory approval steps and document requirements. Our tests passed, because they only reflected what the AI had built — not what the spec required.
The shift was to write tests directly from specifications that we kept in an md file called FEATURE-DESCRIPTION.md. Every business rule and requirement became a test case. Only unit tests generated in that way should allowed us to properly verify AI generated code.
This change turned tests into an enforcement mechanism that pulled AI output back toward the spec. It also caught scope drift — like undocumented optional fields — before they spread into the system. The takeaway: tests must prove compliance with the business spec, not just the code’s behavior.
Our QA lead Davit is currently working on establishing QA plan before starting projects entailing heavy use of AI.
Lesson 3: Do Weekly WIP Reviews for AI-Assisted Work
Without interim reviews, our pull requests ballooned to 1,500+ lines. Reviewing them was slow, painful, and full of late surprises. Bugs and hallucinations that could have been cheap fixes turned into expensive reworks.
For this reason, we are now introducing weekly Work-In-Progress (WIP) reviews for any feature that took more than a week to build. These aren’t formal signoffs and do not result in merging things back to master, just checkpoints where we look at the latest diff and asked simple questions:
Does the code still match the spec?
Does it integrate with sibling modules?
Are there signs of redundant code or AI hallucinations?
Are tests aligned with the business rules?
The results we expect to achieve: hallucinations and code quality issues caught early, smaller diffs to review, and smoother final PRs. As we put it: catch hallucinations when they’re still cheap, not when they’ve grown roots across your codebase.
Lesson 4: Plan QA Before You Write Code
AI makes it easy to start coding immediately, but without QA planning, you risk building features that “work” in isolation and fail in real scenarios. We learned this when the loan processing module handled disbursements correctly but broke when undoing disbursements or validating collateral.
Now we intend to QA before development begins. The plan is lightweight — a checklist of happy paths, edge cases, integration checks, failure modes, and regression risks. Writing this forces us to think through requirements in detail and often reveals missing pieces before coding even starts.
As we came to say: if you don’t know how you’ll test it, you will not be able to know how to complete it.
Lesson 5: Don’t Over-Rely on AI — Always Review your Code
AI can write code fast, but it cannot focus strictly on your domain and specs as it always uses the use-cases and code that it was trained on.. We learned this the hard way: performance issues from missing eager loading, security gaps from absent authorization checks, and scope drift from extra parameters that didn’t belong.
The fix was to treat AI like your own, well trained junior developer: helpful, but in need of review. Always put guardrails in place:
Linters, static analysis, and schema checks.
Security scanning for vulnerabilities and unsafe patterns.
A short manual review checklist: spec compliance, style, validations, redundancy, and tests.
The mindset shift is just as important. Bad output should be rejected quickly, re-prompted with tighter scope, and taught the AI incrementally. We can trust but always verify.
The takeaway: AI can write code fast, but only you can make sure it’s the right code.
Conclusion
Vibe coding — trusting AI and momentum over discipline — can get you moving quickly, but it builds hidden debt. For now, fully relying on this approach isn’t sustainable. In projects of any meaningful scale, a hybrid model is still necessary: using AI to accelerate progress while applying structured engineering practices to manage risk and control technical debt. The five lessons we learned should help us reframe how we work with AI: generate code in smaller increments, anchor tests to specs, review progress weekly, plan QA before coding, and never skip code review.
AI isn’t a replacement for developer discipline — it’s an amplifier. If you bring good habits, AI helps you move faster without breaking things. If you skip the guardrails, it just digs holes faster. The challenge to every developer experimenting with AI is this: don’t just chase vibes — build a process that keeps your code honest.
About Vibe Coding: 5 Lessons From The Trenches Guide
This guide was authored by Enedia Oshafi, and reviewed by Mladen Lazic, CTO at Scopic.
Scopic provides quality and informative content, powered by our deep-rooted expertise in software development. Our team of content writers and experts have great knowledge in the latest software technologies, allowing them to break down even the most complex topics in the field. They also know how to tackle topics from a wide range of industries, capture their essence, and deliver valuable content across all digital platforms.



