Back to Posts

Reflections after a year of vibe coding

Disclaimer: These opinions are mine alone. They don't speak for my employer, my family, or my friends. They're highly opinionated, potentially flawed, and might contain incorrect data. Take them for what they are: one engineer's reflections on a year of shenanigans with AI.

The Journey: Three Distinct Stages

Overall, my journey has gone through three distinct stages, each with its own challenges and revelations.

Stage 1: Exploratory

The first stage was exploratory, where I was learning what vibe coding actually meant. What does it even entail? What kind of impact could it have on my general productivity? How are people actually using it? What are some best practices? Is this even practical? What are the best tools and techniques?

This exploration was limited to two main activities:

  • Using autocomplete for existing projects: integrating AI assistance into my current workflow (aka copilot mode)
  • Creating small end-to-end projects: building small problems, scripts, and personal projects from scratch with AI tools (aka agentic mode)

Key Observations from the Exploratory Phase

1. It is incredibly addicting

If you are an engineer who loves a dopamine hit from writing code, solving bugs and issues, thinking about architectural problems, and solving business problems, vibe coding is incredibly addicting. Seeing ideas come to life in some capacity within a matter of minutes creates a rush where you want to jump from one deliverable to another, from one feature to the next.

I've never felt anything like it. You'll notice I'm not using the word "empowering" here, which isn't because it's not empowering. It definitely is. But I think that's been very obvious. I especially want to highlight that it becomes addictive, particularly for engineers who draw a lot of joy from their work, from building things, from creating things.

#PaceYourself.

2. It is also overwhelming

While it is addicting, it's also overwhelming. You'll stand at the edge of infinite possibility. Every product, every feature, every idea that's been fermenting in the back of your mind suddenly feels within reach. The only barrier left is you. The tools are there. The capability is there. Nothing is stopping you anymore.

For people who are builders and creators it can be unsettling to feel that now all it takes is for you to execute. It's overwhelming because there's a sudden realization that now, many things you can achieve are not limited by lack of tools but by initiative from you.

You become the bottleneck.

#CalmYourself.

3. The risk of over-engineering

When using vibe coding tools and AI assistance to recommend architecture, there might be many things it recommends without really thinking about your scale. Unless you yourself are incredibly aware of these warning signs, that you probably don't need that level of complexity, it can even from the beginning put you on the wrong path. You might start integrating more tools, libraries, and dependencies than you ever would have needed.


Stage 2: Workflow Refinement

Stage 2 is when I moved from exploratory to building an actual genuine workflow, refining how I could use different manners of vibe coding and actually employ it into my day-to-day work.

1. Choosing Your Tools: It's About CX, Not Just Models

The first question isn't "which model?" but "which tools?" Here's why: if you're using any of the top 5 models (Claude, GPT, Gemini), they're all basically at par for what matters to you.

What actually matters? The CX. Your development experience.

We've watched this evolution happen in real time:

  • Early on: IDE-based workflows dominated
  • Earlier this year: Command line agents took over, work became more parallelized, environments more organized
  • Now: Sub-agents running in the background

Here's the thing about AI tools: they're such productivity enablers that they can overwhelm you with the different ways they can be utilized. You need to be conscious about your workflow you are using and context you're feeding your brain while building.

That's why finding the right tools and CX for your workflow isn't just important. It's fundamental.

#ContextEngineeringForYourBrain.

2. Managing Your Time While AI Works

Another crucial part of using these tools is how you use your time while they're running. While vibe coding, you'll have a lot free time at your hands, and it can get frustrating for several reasons:

  • You really don't know what to do in that time
  • While you're waiting, you lose context or your train of thought as you're working on those things
  • Some people try to work in parallel on another part or component of that project. But then you end up with the risk of doing multiple things at the same time. You can't focus on one thing. What if something goes wrong with one component you're building and your focus is away from it? When you try to debug that component later, you have lost context.

This is why the CX and workflow gets really important.

3. Building Context and Awareness of Changes

How do you actually build your own context and awareness of the changes being made while these coding agents are running? There are a few different approaches:

Approach A: Code First, Learn Later

Ask an agent to write a huge chunk of code, then ask the agent to explain the code to you. You can do it in several ways:

  • Ask the agent to give you a summary
  • Ask the agent to explain the how and why of each feature it has added
  • Ask the agent to go through the different modified files one by one

Approach B: Plan, Review, Approve (My Preferred Method)

Instead of allowing the agent to write a lot of code at the same time, ask the agent to plan the code it's going to write. You review it, talk to it, build an understanding that it makes sense, and approve it. Then, even when it starts to implement that code, you use the option of approving each piece of the code that is being added.

While this is more time-consuming, it keeps your focus on the code at hand. You have a much deeper understanding of what changes the coding agent is trying to make.

My approach: Unless it's a very quick, short-term scripting project, I'm not comfortable letting the agent write a lot of code or make a lot of changes. I like to approve every couple of lines of code that an agent is adding to my codebase.

4. Building Historical Context

The third thing you'll encounter is: "How do you continue to build the historical context of the changes you've made so far?"

Even with Claude or Cursor having the entire codebase available, they sometimes can't discern the hidden context. Reading between the lines, if you will. For instance:

  • The scale you're trying to handle
  • The kind of customers you're serving
  • When is it important to index on latency and do things fast vs. when it's okay to wait?
  • Which tools might be easy for the team to use? Which has more community support? Which is cheaper?

Some of these nuances might be missed. At the same time AI could miss a lot of recent context because these models are trained on older data. It might not know:

  • What recent APIs are available
  • What recent advancements exist for a model
  • If a particular LLM has a newer model available or a new API to use

The Solution: Build Historical Context in Your Codebase

Document the thought process of what the code is intending to do. You have the choice of either building your own schema or using a pre-existing one.

This should include:

  • A PRD (Product Requirements Document) that has information which mostly remains static
  • Checkpointing the thought process over time, perhaps in a Situation-Decision-Reason-Impact format

Even if the LLM isn't able to index these documents sufficiently, the checkpointing will be useful for you to understand what your thought process was over time as you were building this project.


Stage 3: Vibe-coding with team

How you vibe code in a team can change based on team size and the impact and scale of the product you're developing. However, some fundamentals uniformly apply.

The Trust Problem

There's a shadow that falls over AI-generated code, even when it works perfectly. A nagging doubt: Did the developer really spend enough time developing, reviewing, and vetting this? And honestly, this skepticism isn't unfounded.

You'll feel it during code reviews. You'll see it when you rush to ship features quickly, only to return later trying to polish what you've built. I've watched it happen again and again: engineers viewing vibe-coded work from their teammates with a certain wariness.

And here's the thing: smart people trust their own instincts. They almost have to doubt others'. It's not malicious. It's how we're wired.

So how do I address it?

1. Be brutally honest about your process

You have to be really honest about: What part of the code has been vibe-coded? What part has been deeply reviewed by you? What part perhaps has not been sufficiently reviewed? What are some potential failures that are possible based on the new code?

Being critical about what you've done with the code (in terms of both your intentions and possible drawbacks) is incredibly useful.

2. Checkpoint with accountability

Another tactical thing: as I said initially, you need to checkpoint your historical context. In a team, you have to do the same, except that for each checkpoint of that historical context, every dev should tag it with their own username and add a summary of the session they've had with the coding agent. This is going to be helpful to build trust.

Breaking Down Work Into Meaningful Chunks

The second thing would be to avoid the pitfall and urge to deliver a lot of features at once. This ties back to what I was first saying. It's very addictive and incredibly empowering, so you try to do a lot at the same time.

Breaking down these features into meaningful chunks which you can build upon is going to make things:

  • Easier to review
  • Easier for the team to understand
  • Easier for you to be more thoughtful about how to test it (vs. thinking about testing as an afterthought after you've built a lot of code)

I would recommend having a discussion in your team to identify those kinds of meaningful, reusable chunks of code. For instance:

  • In a team of maybe two people, it's perhaps acceptable to write five APIs at the same time in one PR
  • If you're working with a team of 10, it might be useful to just do one API at a time

Breaking down code into meaningful, usable chunks (even when you're writing them through AI) is the second piece of the puzzle.

Test-Driven and Spec-Driven Development

The third thing, and perhaps it's fundamental to almost all three stages, is building a practice of doing test-driven and spec-driven development.

This is where you need to give very clear directions about:

  • The kind of feature you want the AI to develop
  • What are its success criteria
  • What are the failure criteria

Those specs could actually be used by the coding agent to write the tests first. It's all right to write the tests in natural language or English first, then convert them into code after the feature has been written.

My typical flow:

  1. Give the specs to the coding agent
  2. Use another sub-agent to refine specs based on the context
  3. From the specs, ask the agent to write tests in English language at this point (not the actual code of the tests)
  4. Ask the agent to actually write the code
  5. Write actual unit tests and sometimes integration tests to test that code

Measuring Your Productivity

It's crucial that you're able to measure your own productivity when vibe coding.

Metrics to track:

1. Lines of code

Typically, most of us will have reference to the number of code lines we produced before we were vibe coding. So it's very easy to compare how many lines of code we're writing now with vibe coding.

2. Code review quality

  • How many rounds of code review are we going through?
  • How many rounds of comments do we get on our PR?
  • How many issues have been opened up on that PR after merging?

3. Cost (time and dollars)

Time cost: Did it end up taking more time for you as you were developing this feature while vibe coding? And why did it take more time? What could you have done differently in your workflow to reduce that time?

Perhaps this was a feature where you had to add like 10 new lines of code, and it would've been easier for you to directly do it on your own versus giving a lot of context to an LLM so that it does it the right way.

Dollar cost: Maybe you had to debug a feature and you were giving too many logs, detailed logs to the LLM, which was ending in a lot of tokens. While ultimately the fix was pretty simple and mostly needed tribal knowledge of how the system worked versus having to analyze logs in very detail.

So are you thinking about things, or are you kind of just leveraging brute force LLM power?

Don't get me wrong. There's nothing wrong with brute-forcing LLM usage. But especially for engineers, where we need to optimize and make our workflows and productivity flows more efficient, it's critical to analyze how we are using our time and not getting lost in this universe of knowledge and agency that LLMs provide us.


Conclusion

At the end of the day, coding through these pre-trained models is definitely useful. It enables you to do more work and think about the bigger picture. The potential is enormous. But the real skill isn't just in using AI to code. It's in crafting a sustainable, thoughtful practice around it. One that makes you more productive without making you reckless. One that empowers you without overwhelming you.

That's the journey. And it's still evolving.