Fail Fast, Fail Safely

Fail Fast, but Fail Safely

Reviewed by Juan Pablo Lorandi, CTO for Azumo

With AI, "fail fast" should mean learning faster before production, not failing faster in it. Give every iteration a falsifiable hypothesis, success criteria set in advance and a decision rule. Keep prototypes separate from products, and run experiments in isolated environments behind feature flags and staged rollouts.

"Fail fast" has been a mantra in software development for years. The idea is straightforward: build something quickly, put it in front of users, learn from what happens and iterate. The faster you fail, the faster you learn, and the faster you learn, the faster you converge on something that works. It is a sound philosophy that has taken many products from rough prototypes to mature ones.

AI coding assistants have greatly accelerated the "build something quickly" part. What used to take a team weeks can now be prototyped in days or even hours. That acceleration has exposed a dangerous misunderstanding at the heart of fail fast. The goal is not to fail faster in production. The goal is to learn faster before production.

Speed Versus Velocity

Speed and velocity are different, and the difference matters here. Speed is how fast you are moving. Velocity is how fast you are moving in the right direction. AI-assisted development gives teams a great deal of speed. Whether it gives them velocity depends entirely on whether the team learns from what it builds.

The risk is subtle. When building is quick, teams can produce several versions of a feature, try different approaches and have working prototypes before lunch. This feels productive. It feels like progress. But if no one stops to ask what each iteration taught them, the team is spinning, not advancing. It is generating code, not insight.

Failing fast has always needed a companion discipline: structured learning. Each iteration should start with a hypothesis, produce an outcome and end in a conclusion. "We believe that simplifying the checkout flow will increase conversion by 10 percent" is a hypothesis. Building a simplified checkout flow and measuring conversion is the experiment. The conclusion, whether conversion went up, down or stayed the same, is the learning. Without that structure, building fast is just building fast.

AI makes this discipline harder to keep, because building takes so little effort that teams skip the hypothesis. Why write a careful hypothesis when you can build three versions and see which one "feels right"? Because feeling right and being right are different things, and the difference matters a great deal when the software handles financial transactions, medical records, regulatory compliance or any domain where consequences are real.

Prototypes Are Not Products

Shorter build times have blurred the line between prototype and product in ways that create real risk. A few years ago, a minimum viable product took weeks or months to build. That investment imposed a natural discipline: teams thought carefully about what to build because building was expensive. The prototype stage was distinct from the product stage because the effort to move from one to the other was large and visible.

Today, a testable prototype can appear in days. An AI coding assistant can generate a working application with a database schema, API endpoints, a frontend and basic authentication in a single session. The prototype looks like a product. It behaves like a product. Stakeholders see it and assume it is a product. That is the danger.

A prototype built in a day carries all the shortcuts, assumptions and unvalidated decisions that a day of work implies. Error handling is minimal. Security is surface-level. Edge cases are unaddressed. Performance under load is unknown. The data model works for the demo scenarios but may not handle the full complexity of real use. None of this is visible from the outside. The prototype looks polished because AI is good at generating polished-looking code.

The discipline required is explicit gates between prototype and product, with evidence required at each gate. A prototype should answer a specific question: Is this the right user experience? Does this workflow make sense? Will users understand this interface? Once the question is answered, the prototype has done its job. Moving to production takes a different process with different standards.

The Azumo SDLC makes that gate explicit by giving exploration its own workflow. A spike (experiment) is one of five workflows, alongside feature, bug fix, small change and docs. Production work runs through the feature workflow: clarify → spec → plan → build → validate → review → deliver, with a person's approval after the spec, after the plan and before shipping. Bugs, features and experiments run in parallel, so exploring does not stall delivery.

Production quality still takes more than a prototype, but not months. For custom software development run on the Azumo SDLC, a well-scoped app typically reaches its first production release in 2–4 weeks, depending on requirements. Larger systems ship as a series of 2–4 week releases.

Where Vibe Coding Fits

One mode of AI-assisted development has come to be called "vibe coding". A developer describes what they want in natural language and iterates rapidly with an AI assistant, accepting or rejecting generated code based on whether it seems right rather than whether it has been verified. The developer works by feel, adjusting prompts and reviewing outputs until the result matches their intuition.

Vibe coding has a legitimate place in the development process. For prototypes, it is very effective. For internal tools with a small, tolerant user base, it can be adequate. For assumption testing, where the goal is to validate an idea before investing in production-quality implementation, it is faster than any alternative.

Vibe coding is not appropriate for production systems, regulated environments or customer-facing applications where reliability, security and correctness are non-negotiable. The problem is not that vibe coding produces bad code. The problem is that it produces code of unknown quality. The developer accepted it because it seemed right, not because it was verified. In a prototype, that uncertainty is acceptable. In a production system processing real transactions, it is not.

Fail fast accommodates vibe coding naturally: use it to explore, to prototype and to test assumptions. When an approach proves promising, switch to a disciplined development process with code review, testing, security analysis and the other practices production software requires. The failure is not using vibe coding. The failure is not making the switch to production engineering when the stakes change.

Scope Creep When Generation Is Fast

One of the subtler risks of AI-assisted development is that scope creep speeds up quietly when generation is quick. In traditional development, scope creep is visible because every extra feature costs developer time. When a stakeholder asks for "one more thing", the team can point to the timeline impact. The cost is tangible and immediate, which creates natural resistance.

When AI can generate extra features quickly, that resistance disappears. "Can you also add an export to PDF?" becomes a five-minute addition instead of a two-day task. "What about a dashboard for managers?" goes from a significant scope expansion to a casual afternoon project. Each addition seems trivial. The cumulative result is a product that has grown well beyond its original scope, with every addition carrying the quality of something built in five minutes.

So apply fail fast to scope, not just to features. Evaluate each proposed addition against the hypothesis the team is testing. Does a PDF export help answer whether users will adopt this workflow? Does a manager dashboard contribute to this iteration's learning objective? If not, it belongs in the backlog, not in the current prototype, no matter how quickly it could be generated. Scope is also what an estimate rests on: every addition still has to be specified, reviewed, tested and maintained, however fast it was generated (see how Azumo prices custom software).

Treat the ease of generation as a temptation to manage, not an opportunity to exploit. Building more is not the same as learning more. Often, building less and observing more carefully gives better insight than building everything and hoping usage patterns reveal which features matter.

Structured Experiments, Not Unstructured Exploration

Failing fast and failing safely requires structure. The structure is not complicated, but it must be intentional. Each pass through the build-test-learn cycle should have four elements: a clear hypothesis about what the team expects to learn, a minimum viable experiment that tests it, success criteria defined in advance, and a decision framework for what happens based on the outcome.

The hypothesis should be specific and falsifiable. "Users will like this feature" is not a hypothesis. "Users who currently complete the onboarding flow in an average of twelve minutes will complete the redesigned flow in under eight minutes" is. It can be measured. It can be proven wrong. It produces actionable information whatever the outcome.

The minimum viable experiment is the smallest thing the team can build to test the hypothesis. AI makes it tempting to build more than the minimum because building is quick. Resist that. The minimum viable experiment is not the least the team can build. It is the least required to test the hypothesis. Anything beyond that is waste, however quickly it was generated.

Define success criteria before the experiment runs, not after the results are in. This prevents the common failure of reinterpreting ambiguous results to support a conclusion the team had already reached. If the criterion was an eight-minute completion time and the result is nine minutes, the experiment failed, and the team learns from it. Moving the criterion afterward to declare success defeats the purpose.

The decision framework sets what happens next. If the hypothesis is supported, what is the next hypothesis? If it is not, does the team pivot, iterate or abandon the approach? Make these decisions deliberately, with input from stakeholders, not reactively in the moment.

Isolated Environments and Controlled Exposure

Failing safely means containing the blast radius of failures. When experiments run in production with real users and real data, failures have real consequences. A checkout experiment that introduces a bug loses real revenue. A data migration experiment that corrupts records creates real cleanup work. Fail fast does not require accepting these risks.

Isolated environments, synthetic data sets and controlled exposure let teams experiment aggressively without risking real harm. Feature flags, also covered in why UAT matters more with AI-assisted development, expose new features to internal users or a small subset of external users. Staged rollouts increase exposure gradually as confidence in a feature grows. Canary deployments send a small share of traffic to the new version while monitoring for anomalies.

None of these mechanisms are new, but they matter more as the rate of experimentation rises. A team that deploys once every two weeks has time to verify each deployment by hand. A team that deploys several times a day needs automated safeguards that detect problems and limit their impact without waiting for a person. Investing in deployment practices for AI-generated code is investing in the ability to fail fast without failing badly.

Measuring Iterations by What You Learned

After each iteration, whether a prototype, an experiment, a feature deployment or a full release, one question shows whether the team is failing fast productively or just failing fast. The question is not "What did we ship?" It is "What did we learn?"

If the answer is "We learned that users prefer the simplified workflow", the iteration was valuable whether or not the code is production-ready. If the answer is "We shipped a new feature", the iteration may have been productive, but the team cannot tell, because it did not structure the work to produce learning.

AI-assisted development makes it possible to ship more than ever. The teams that succeed measure progress by insight, not output. They use the speed AI provides to test more hypotheses, check more assumptions and reach the right solution sooner, not just to produce more code. Shipping without learning compounds over time: technical debt accumulates, user trust erodes, and the codebase grows in directions that do not serve the business.

Related Chapters