Why is my AI-built app stuck at 80% and what does finishing it actually involve?
The answer
The last 20% is not more features. It is the invisible work — the security boundary, the failure paths, the operational scaffolding — that the AI was never asked to build and cannot verify. It is a finite list rather than a mystery, and no amount of further prompting substitutes for going through it.
By Muhammad Bilal12 min read
The short version
- The 80/20 split is not about effort, it is about visibility. AI coding tools are extremely good at work that can be looked at and judged, and structurally weak at work whose only evidence is that nothing bad happened.
- The prompt loop stops converging because the model is editing things it has no way to test. Ten more attempts is not ten times more likely to work — it is the same attempt with different wording, and each lap costs credits.
- The remaining work is a list, not a fog. There are about seven items on it, they are the same seven every time, and most of them are measured in hours rather than weeks.
- You are probably not at 80%. Most apps that feel 80% done are around 80% of the visible surface and close to zero of the invisible half — which is why the last stretch feels infinitely long.
- The decision that saves the most money is deciding what you are not going to fix before launch, rather than discovering it at three in the morning.
There is a specific feeling that brings most people to a page like this one. The app works. You can show it to someone. The screens are there, the buttons do things, the demo goes well — and yet it has not moved in three weeks, every fix seems to break something else, and you have started to suspect that the finish line is not where you thought it was.
That feeling is accurate, and it is not a reflection of you or of the tool. It is the single most predictable thing that happens to AI-built software, and it happens at roughly the same point every time.
Here is what is actually left, why prompting your way through it stops working, and what it takes to close.
Why it stalls in the same place every time
The useful way to think about this is not "80% of the work is done". It is: 100% of the visible work is done, and close to none of the invisible work has started.
Every AI coding tool — Lovable, Bolt, Replit, Cursor, all of them — is optimised on a loop that runs on visible evidence. You describe something, it generates, you look at the result, you say yes or no. That loop is extraordinarily effective for anything you can see. A layout, a form, a dashboard, a flow between three screens: these are exactly the shape of problem where a fast generate-and-look cycle beats a human writing it by hand, and it is not close.
The loop has no equivalent for work whose only evidence is a bad thing not happening. There is no screen that shows you that a stranger cannot read your database. Nothing renders differently when a duplicate webhook is handled correctly. A missing database index looks identical to a present one until the table has two hundred thousand rows in it.
Veracode's Spring 2026 update to its long-running study of AI-generated code puts a number on the same idea. Across more than a hundred models, syntax correctness has climbed from roughly 50% in 2023 to over 95% today. Over exactly the same period, the security pass rate has stayed flat at about 55%. The models got dramatically better at producing code that runs and no better at producing code that holds. That is not a scandal about AI. It is what you get when one half of the job has a feedback signal and the other half does not.
So the 80% is not a coincidence and it is not a measure of effort. It is the boundary between the part of software that can be judged by looking and the part that cannot.
Why the prompt loop stops converging
This is the part that costs people the most money, so it is worth being precise about the mechanism.
When you hit a problem that lives in the invisible half and you describe it to the AI, it will produce a fix. The fix will look right. It will be written with complete confidence. And you have no way to evaluate it, because the thing it is supposed to have fixed was never visible in the first place — so you redeploy, the symptom is unchanged or has moved somewhere new, and you describe it again.
The reason this does not converge is that nothing in the loop is measuring anything. A normal debugging loop narrows: each attempt rules something out. This one does not narrow, because there is no test being run between attempts. Ten more prompts is not ten times more likely to work than one; it is the same attempt in ten different phrasings.
The clearest example is the one half of r/lovable is currently living inside. You turn on row-level security, your app breaks, you paste the error into the chat, it rewrites the policy, it breaks differently, and eventually you get infinite recursion detected in policy for relation — a policy asking a question that requires reading the very table the policy protects. Each lap through that loop is real money. Lovable's own documentation prices a trivial visible change like "Make the button gray" at half a credit and "Add authentication with sign up and login" at 1.2 credits; a loop that runs twenty times on an invisible problem is not a rounding error on a plan with a monthly credit ceiling.
The tell that you are in this loop rather than making progress: the AI keeps agreeing with you. Every message begins by confirming that yes, that is exactly the problem, and here is the fix. A loop with a real measurement in it produces disagreement sooner or later. A loop without one produces agreement forever.
What the last 20% actually consists of
The good news, and it is real good news, is that this is a list. It is not an unbounded fog of "engineering". It is roughly seven things, they are the same seven in nearly every app I look at, and several of them take an hour.
One: the access boundary. Who can read and write which rows. In a Supabase-backed app this is row-level security, and it is where the well-known failures live — an unauthenticated stranger reading your users table is this item being missing. Switching it on is one click. Writing policies that let your real users through while keeping everyone else out is the fiddly part, and it scales with the number of user roles, not with the number of screens. If you want to know whether you have this problem before you spend anything, there is a five-minute browser check in is my Lovable app secure? that answers it definitively.
Two: authorization, which is not authentication. The login screen exists — that part is visible, so it got built. The check that runs afterwards on every request, asking whether this user may touch this record, is invisible, so it usually did not. This is the item behind changing /invoice/1042 to /invoice/1041 and seeing someone else's invoice.
Three: the failure paths. Everything that was demoed took the happy path, because the happy path is what you demo. What happens on a declined card, a duplicate form submission, a webhook that arrives twice, a user who closes the tab mid-checkout, a third-party API that times out. Payments are the expensive version: the characteristic outcome is not fraud but slow revenue leakage, people paying and not getting access or getting access and not paying, in ones and twos, for months.
Four: behaviour under real data. Your app was tested against fifty rows, so nothing was slow and nothing looked wrong. Lists that load every row, twenty-one queries where there should be one, and no indexes on the columns you filter by are all invisible at your scale and severe at a real one. This one is usually the cheapest big win available — a focused day frequently takes a screen from six seconds to under one. It is worked through in detail in why your app breaks when real users show up.
Five: knowing when it breaks. No error tracking, no alerts, no logs anyone reads. The way you currently find out that signup has been failing is that someone emails you, or more likely does not email you and simply leaves. This is the highest-value hour on the entire list, because it converts every other item from theoretical to observable, and the free tiers are sufficient for almost every app at this stage.
Six: the ability to change it safely. No staging environment, so every change is tested in production by your users. No tests, so nothing tells you when a change breaks something two screens away. This is the actual mechanism of being stuck, and it deserves more than one line, so it gets a section below.
Seven: knowing what you own. Where the code lives, whether the database can leave, what is in an export and what is not. This is not urgent in the way the first two are, but it is the item that determines whether the next six months are pleasant, and it is much cheaper to sort out before there is production data. There is a full accounting of what actually comes out of each platform in what you actually own when you export.
All ten of these failure modes, with how to test for each one yourself, are in the ten problems every AI-built app has in production.
The sixth item is why it feels infinite
Most people describe being stuck as "the last features are hard". They are usually not. What has actually happened is that the cost of every change has quietly gone up.
Early on, a change costs one unit: you describe it, it happens. Later, the same change costs one unit plus whatever it breaks elsewhere, plus the time to notice, plus the time to fix that, plus whatever that breaks. Nothing about the feature got harder. The surface it lands on got more fragile, because there is no test anywhere telling anyone what a change touched.
That is why progress does not slow gradually — it slows, then stalls, then reverses, and the reversal is the part that feels like failure. You are not going backwards because you are doing it wrong. You are going backwards because the app has reached the size where changing it without a safety net costs more than the change is worth.
The fix is deeply unglamorous and works immediately. A staging environment, which is nearly free and stops changes being tested on your users. Then tests on the three or four flows that would actually cost you money — signup, checkout, the core action — and specifically not on everything, because a test suite nobody maintains is worse than none. That is not a big project. It is the difference between an app you are afraid of and one you can keep building.
How to tell where you actually are
Stop asking what percentage of the features are done. Ask what happens when things go wrong. These are the questions, and "I don't know" is a legitimate and very common answer to all six:
Can a logged-out stranger read your data? Can a logged-in user reach another user's records by changing a number in the URL? If a payment fails halfway, what state is the account left in? If signup breaks at two in the morning, how do you find out? If a deploy makes things worse, how do you get back? If the database were wrong tomorrow, has anyone ever actually restored a backup and watched the app come up?
Six questions. If you can answer five of them concretely, you really are near the end and the remaining work is small. If most of them are "I don't know", the visible half is genuinely finished and the invisible half has not started — which is the real answer to why an app that looks 80% done has not moved in a month.
What it costs
Two costs, and people usually only count one.
The one nobody counts is the cost of staying in the loop. Credits burn per attempt and a non-converging loop has no natural end, so this cost is unbounded in a way a fixed piece of work is not. Add the exposure items, which are the only ones that get worse while you sleep — a data leak does not need traffic, it needs time.
The one people do count is the work itself, and the honest answer is that it varies by one thing far more than any other: how many different kinds of user your app has. A single-role app with payments is a small, well-defined job — the access rules are simple because there is one shape of user, and most of the seven items above are configuration rather than code. An app with organisations, invited members, shared records and different permission levels is a materially different piece of work, because every one of those combinations is a rule somebody has to get right.
For context on the surrounding numbers rather than the labour: running a small production SaaS in 2026 lands around $70–115 a month in fixed subscriptions once you have a real database plan, real hosting, error tracking and email — and none of that is optional for an app taking real money. That is broken down line by line, with the parts people usually miss, in what it costs to take an AI prototype to production in 2026. On labour rates, the only 2026 figure I am willing to quote is freelancermap's Freelancer Study 2026, which surveyed over 5,400 freelancers and reported an average of €103 per hour — but that is all freelance disciplines across the DACH region, not a backend rate, and I would rather give you a soft number with its limitations attached than a confident one I made up.
The order to do it in
Not top to bottom. The list has a natural sequence and following it saves both money and nerves.
Items one and two first, this week, regardless of what else is happening, because they are the only ones where the damage compounds with time rather than with traffic. Then item five, the error tracking hour, because until that exists you are diagnosing everything blind. Then item six, staging, because it stops the bleeding on every change after it. Then three and four, which are the ones actively costing you users and money. Then seven when you have breathing room.
And one thing that is not on the list but should be: decide what you are not fixing. Plenty of good businesses run profitably on a stack that would fail half of this. The difference between those and the ones that fall over is not how many items they closed — it is that they knew which ones they were living with and had chosen to, rather than finding out during an incident.
If you would rather not do this alone
If you recognised your app in this, that is the normal reaction, and it is worth saying plainly that arriving here means the tool did its job. The first 80% used to take months and now takes days. That is a real and enormous thing. The job just does not end where the demo does, and nobody mentioned that at the start.
I do a Production-Ready Audit for precisely this situation: all seven items checked against your actual app rather than against a description of it, with a written fix list in priority order and an honest cost beside each one, so the decision about what to fix and what to live with is yours to make with real information. From $499, back in five to seven days. If it comes back clean I will tell you so and you keep your money.
If you would rather just find out whether you are stuck or nearly done, send me a description of where it stopped moving and I will tell you which of the seven you are looking at. No charge and no pitch — that question usually has a short answer and it seems unreasonable to bill for it.
There is more on getting a stalled build actually shipped on the MVP development page, on the deeper repair work on the AI SaaS rescue page, and if you are weighing whether to fix what exists or start again, that decision has its own guide in rescue or rebuild.
Follow-up questions
What people ask next
Can I finish the last 20% with more prompting?
Some of it, yes — anything with a visible result is fair game, and the tools are genuinely good at it. What does not close by prompting is anything whose correctness cannot be seen on screen: database access policies, authorization checks, webhook idempotency, index strategy. The model can write plausible code for all of those and has no way to tell you whether it worked, so you get confident answers and an unchanged problem.
How do I know whether I am at 80% or at 40%?
Ask what happens when things go wrong rather than when they go right. Can a logged-out stranger read your data? Does a failed payment leave the account in a sensible state? Does anyone find out if signup breaks at 2am? Is there a way back from a bad deploy? If most of those answers are 'I don't know', the visible part is nearly done and the invisible part has not been started.
Do I have to throw away what the AI built?
Almost never. In the large majority of apps I look at, the generated code is a reasonable starting point and the gaps are in the layers around it — the database rules, the error handling, the deployment configuration. Rewriting from scratch throws away the part that worked in order to redo the part that was never the problem. There are cases where a rebuild is the honest answer, and they are narrower than most people fear.
How long does it take?
It depends much more on how many user roles your app has than on how many screens it has, because roles are what make access rules hard. A single-role app with payments is usually a small number of focused days. An app with organisations, invitations and shared records is a genuinely different job. The reliable predictor is not the size of the app — it is how many different kinds of user can see different things.
What does it cost to just leave it as it is?
That is a real option and sometimes the right one, but price it honestly. The cost is not zero — it is the compounding credit spend of a loop that does not converge, plus the exposure items that get worse with time rather than traffic. Deliberately shipping with known gaps and a written list is a defensible business decision. Shipping without knowing what the gaps are is not the same thing.
Related reading
Rapid MVP Launch
A production-grade MVP with auth, database, billing and deployment done properly the first time.
From $699 · 30–45 days

Muhammad Bilal
Full Stack AI Developer · Faisalabad, Pakistan
I build and rescue production AI SaaS products with Next.js, Supabase, Stripe and Claude. Most of my work is finishing apps that were started with Lovable, Bolt, Cursor or Replit and stalled somewhere between working and shippable.
5.0★ · 100% job success · 35+ projects delivered
