9 min read

VibeCoders vs Software Engineers: the difference shows up in production

Generating code with AI is now the easy part. The hard part is still discovery, design, security and answering for what happens after the deploy.

AI Software engineering Security How we work

Three years ago, showing a working app in two days was a signal of talent. Today it is an afternoon with a well-prompted model. The demo stopped being evidence of anything, and that changes the question a client should be asking when they hire software.

The question is no longer whether someone can build it. It is who answers when it breaks.

What vibe coding actually is

The term caught on to describe a way of working: you describe what you want to a model, accept what it produces, test it loosely and move on. You do not read the code closely. You trust that the result looks right and does what you asked along the happy path.

And it works. It works surprisingly well for prototypes, for internal scripts, for validating an idea on a Saturday. We have no interest in dismissing that: we work the same way when we are exploring and there is nothing to hold up yet.

The tool is not the problem. The problem is when that mode of working gets billed as engineering, and the client finds out the difference six months later.

Where it breaks

Code generated without judgment does not fail in the demo. It fails at the edges, and the edges are exactly where the business lives.

On concurrency. An endpoint that deducts inventory looks correct when you test it alone. With two hundred simultaneous requests during a promo, you sell what you do not have. Nobody catches it skimming the code, because the code “looks fine”: the bug is in what was never written, the missing transaction and lock.

On money. A charge without idempotency processes twice when the customer loses signal and retries. In a demo it is invisible. In production it is a refund, a chargeback and an uncomfortable conversation.

On data. A model will happily generate a query that pulls everything and filters in memory. With a thousand rows it flies. With two million it takes the server down, and by then there are customers on it.

On security. The most common case is not an exotic injection: it is an endpoint that trusts the identifier the client sends and returns another company’s data. It passes every test, because every test was written with a single user.

None of these mistakes happen because AI is bad at writing code. They happen because nobody asked it the right question, and asking the right question requires having been in the incident before.

The work that happens before the first line

This is the part vibe coding does not skip out of carelessness, but because skipping it is exactly the promise: with a model you have code in seconds, so starting to build becomes cheaper than deciding what to build.

On a serious project, four things happen before any code.

Discovery. Sitting with the people who live the problem and understanding the real operation, not the one on the org chart. Who does what, where the process stalls, what gets solved by hand today. Half the requirements a client brings in at the start change once someone asks why.

Requirements. Turning “we need an orders module” into something buildable: what states an order has, who can change them, what happens on a partial return, what to do if the customer cancels after dispatch. These questions are not bureaucracy. They are 80% of the system’s complexity, and if they are not answered now they get answered on their own, badly, inside the code.

Planning. What gets built first and why. A phased plan where each phase leaves something running in production, not six months of invisible work integrated at the end. With estimates someone stands behind, not a number picked to win the proposal.

Design. Flows and screens connected to a system, not loose screens. And technical design: the data model, the boundaries between modules, what gets exposed as an API, how state is handled. On a custom software project this is half the real work. These decisions are made once and paid for over years.

A language model can help in every one of these stages, and we use it there too. What it cannot do is have them for you. Ask it for code without doing this work and it will give you code: coherent, tidy, and built on assumptions nobody validated.

When a project falls apart at month six, it is almost never because of a bad line of code. It is because nobody defined what happened on a partial return.

Security does not autocomplete

This is where the difference worries us most, because security failures do not show up as an error. They show up as nothing, until someone finds them.

A model generates functionally correct and quietly insecure code with equal ease, because nobody told it what the threat model is. And the threat model does not come from the code: it comes from understanding what data you hold, who wants it, and what happens if it leaks.

What we always review, and never delegate:

  • Authorization, not just authentication. Knowing who you are is the easy part. The hard part is verifying on every operation that this user may touch this resource, even when the identifier comes from the client. Most real leaks we have seen are this, not broken cryptography.
  • Personal data handled deliberately. What is stored, for how long, who queries it and what gets logged. Colombia has a data protection law that applies from your first user, and in the sectors we work in that is not a checkbox: it is an audit.
  • Secrets and configuration. Credentials out of the repository, rotation possible, least privilege per service. It sounds obvious and it is still the most common finding when we review an inherited project.
  • Dependencies. Every package you add is third-party code with the same access your application has. We review what gets installed and why, and keep an inventory of what needs updating when a CVE lands.
  • Logging and traceability. If something happens, there has to be enough of a trail to reconstruct what occurred and who did it. Without that, an incident is a discussion of opinions.
  • Adversarial review before production. Someone reading the change asking “how do I abuse this?”, which is a different question from “does this work?”.

None of this is exotic or expensive. It is routine for a team that has worked in healthcare and finance, and it is part of how we approach any enterprise software project, and it is exactly what goes missing when software is built by accepting suggestions.

The real difference: who carries the risk

A software engineer is not someone who writes code better than a model. In many cases they no longer do, and pretending otherwise denies the obvious.

What an engineer does is something else:

  • Decides what is hard to reverse. Whether the database isolates by row, by schema or by instance. Whether state is derived from events or stored in a field. These decisions do not change with a prompt six months later: they change with an expensive migration.
  • Knows what to ask before building. How many transactions per second on the worst day, what happens if the payment provider does not answer, who can see whose data. Software quality depends more on these questions than on the language you pick.
  • Recognizes what they cannot see. Experience is what makes you distrust something that looks finished. A developer with years in transactional systems reads a flow and knows where it will hurt, because it already hurt once.
  • Answers for the delivery. When something goes down on a Friday at six, the tool does not pick up the phone. A person does, and that person has to understand what shipped.

So, do we use AI?

Every day, and heavily.

We use it for boilerplate, to explore three design alternatives in an hour instead of a week, to widen test coverage and find edge cases, to document and refactor legacy code. It makes us much faster at the mechanical part of the work.

What we do not do is hand it the decisions. Architecture is defined by us, and we explain the reasoning. Everything that reaches production goes through human review, no exceptions. Critical business rules and sensitive data handling get designed, not autocompleted. And if something breaks, we answer for it.

That boundary is not purism. It is the only way the speed AI gives you is not paid back later with interest.

The debt that is not on the invoice

There is a pattern we keep seeing in clients who arrive after a cheap project: the software exists, it looks good and it does what it promised. But nobody knows why it was built that way, there are no tests, the decisions are undocumented, and every new change breaks two old things.

Rebuilding that costs more than doing it right the first time. Not because generated code is bad, but because nobody was behind it holding the system coherent while it grew.

The savings were real. So is the debt.

How to choose who builds with you

If you are evaluating who to hire for software, these questions separate quickly:

  1. What architectural decisions did you make and why? If there is no answer, there was no decision.
  2. What happens when load goes up tenfold? There should be a number, not a “it scales well”.
  3. How is what reaches production reviewed? There should be a human in the loop, with a name.
  4. Who owns the code and what happens if I leave? If the answer is awkward, you already know.
  5. What will you do with AI and what will you not? Say it upfront. We have ours written on the landing page.

None of these questions are about the language, the framework or the tool. They are about judgment, and judgment is still what gets hired.

What we believe

AI does not replace software engineering: it replaces the part of software engineering that was never the valuable part. Writing the line was always the means. The value was knowing which line, why, and what breaks if it changes.

We are fast because we use these tools. We are dependable because we have spent more than a decade building systems that cannot go down, in telco, healthcare and finance, where a mistake is not a ticket but a real consequence.

Both together are the offer. Neither one alone is worth much.

Want to build something like this?

If what you are reading sounds like how you want a team to work with you, let us talk about your project.