Why one-shotting your whole AI app is the fragile part
One-shotting fails because every wrong assumption baked in before the first line of code is expensive to fix after the build lands.
Last updated
One-shotting is the idea that you describe an app, the AI builds it, and it works. It sometimes does. The problem is what happens when it does not. A wrong assumption about persistence, payments, or what the app is actually for costs almost nothing to fix if you catch it before the build. After the build, the same assumption can mean rebuilding from scratch, because it reaches into the database schema, the routing, the deployment shape, and the QA path.
Why does one-shotting break?
When an AI builds an app in one pass, it has to guess at every fork it cannot see. Does this app need a database? Does it take payments? Is it a demo or a real product? Each guess is a bet, and the bets compound. If the first guess is wrong, the code built on top of it is not free to change. It has to be undone.
The fragile part is not the code quality. It is the lack of a checkpoint. A human team would never start writing code without agreeing on what they are building, but a chat box has no reason to pause and ask. It optimises for producing something, not for producing the right thing. That is why a wrong assumption after a one-shot build is not a bug fix. It is a rebuild.
What happens before the first line is written?
On this platform, the chat produces a blueprint before anything is built. The blueprint is what the platform thinks you asked for, written as a list of capabilities you can edit, remove, or add to. If it assumed you wanted user accounts and you did not, you remove them here. If it assumed payments were out of scope and they are in, you add them here. This is where a wrong assumption is cheap. After the build it is not.
The other decision that has to happen before the first line is the build type. There are three. A demo has no payments, memory only, and one QA pass. A delivery app has a real database, payments wired to a client's account, and QA up to four iterations. A product has a real database, payments provisioned automatically, and QA up to five iterations. The type is chosen before building because a demo that later needs to take money is not upgraded in place. It is rebuilt as the type it should have been. Payments and persistence reach into every part of the app, and changing them after the fact means the work was wasted.
What does QA actually catch?
A build that does not pass does not get called done. A separate agent opens the deployed app in a real browser and checks it against what the blueprint said it would do. This is not a unit test or a lint pass. It is an agent driving Chromium, the same Ghost Browser that is a cluster tool here, clicking through the app the way a user would.
The iteration count matters because it is the opposite of one-shotting. A delivery build gets up to four QA passes. A product gets five. Each pass is a chance to find that the app does not do what you meant, not what you said. If the first pass finds a gap between intent and output, the builder fixes it and QA runs again. One-shotting gives you one pass at getting it right. The blueprint plus QA gives you a checkpoint before the build and several after it.
What went wrong when things were one-shot?
A major Postgres bump crash-looped a database because an image tag moved from Postgres 15 to 16 and Postgres does not upgrade its data directory across a major version on start. The container came up, refused the existing data, and restarted forever. The fix was not a setting. The database is now pinned to its major version, and a major upgrade is a deliberate migration, never a tag change. This is the shape of fragility that one-shotting creates: a single assumption about a version tag that nobody checked, and the app is down until somebody notices.
Storage replicas starved etcd on a single node. Longhorn was configured with multiple replicas on one node, which produced replication traffic and disk contention until the control plane crash-looped and the cluster stopped responding. Redundancy across replicas of the same disk is not redundancy, it is load. The fix is a rule: on a single node, one replica.
A build capped its own steps and looped forever. A walk was given a step limit shorter than the work honestly took, so it was killed and re-dispatched hourly while the abandoned run kept finishing successfully with results nobody collected. Eight runs in one night, millions of tokens. The fix was to let the browser decide what is alive and to collect work that finishes after a timeout rather than throwing it away.
These are not general reliability problems. They are the specific things that go wrong when a system is built in one pass and nobody builds a checkpoint into the process. The blueprint, the build type, and the QA iterations are the checkpoints. If you want to see how the full build path works end to end, there is a walkthrough at /learn/how-do-you-build-an-app-with-ai-agents, and if you are asking what production-ready actually means after the build lands, /learn/what-does-production-ready-actually-mean-for-non-coding-founders covers that. On this platform, the answer to one-shotting is structural: you get a blueprint to correct before anything is written, a build type that forces the persistence and payments decisions up front, and a QA agent that verifies the deployed app in a real browser rather than trusting the first output.