Custom Software

Rebuilding an AI-Built App for Production: What It Costs

The prototype is not 80% of the product. Here is what survives the rebuild, what always gets thrown away, and what the cost really tracks.

Custom SoftwareMohsin Ali, CTO at DevfinixBy Mohsin AliPublished 13 min read
A building mid-construction behind scaffolding, a structure not yet load-bearing

If you need to rebuild an AI-built app for production, the honest starting point is that the prototype is not 80% of the product. It is closer to a very good specification. What carries over is everything that encodes a decision — screens, flows, copy, scope, the things you learned when real people used it. What gets replaced is almost everything underneath: how users are authenticated, how data is shaped, how one customer's records are kept away from another's, what happens when a request fails, and how you find out that it did.

That is not a criticism of Lovable, Bolt, Replit or v0. They are built to get a working thing in front of you quickly, and they do that better than any team can. The gap only appears at the point where an app stops being a demonstration and starts holding data that somebody would be upset to lose.

Why the wall exists

A prototype has one job: show that the idea works. So the generated code optimises for a visible result on the happy path. Every tool in this category does the same reasonable things to get there.

Queries fetch what the screen needs, filtered by whatever the current page knows about. Auth is whatever the starter template provided, usually with permissions enforced in the interface rather than at the data layer. Validation lives in the form component. Errors surface as a toast, or not at all. There is no migration history, because the schema was edited in place as the app grew.

None of that is wrong for a prototype. It becomes wrong the moment a second customer signs up, or someone opens the network tab.

The wall is usually hit in one of four ways. You add a second customer and realise the data model has no concept of who owns a row. You try to change a table and discover there is no safe way to apply that change to data you already have. Something breaks in front of a user and you have no idea what happened. Or you look at what the client is allowed to ask the database for, and it is everything.

What survives the rebuild

Start with the good news, because it is genuinely valuable and people undersell it.

The interface. Layout, component structure, spacing, states, the copy in the buttons. If the prototype produced React with a utility-class stylesheet, a large amount of that markup ports across with modest editing. The design decisions inside it are worth more than the code. What usually does not port is how it renders: prototype output tends to be client-rendered throughout, and client-only rendering of above-the-fold content is one of the structural ways a page prevents its own Largest Contentful Paint.

The product scope. A prototype that exists is the most precise brief you will ever write. It settles arguments that otherwise take weeks: what is in v1, what a screen contains, what the navigation looks like. Handing an engineering team a working app to build "properly" is a far better starting point than a document.

The validated flows. If you put the prototype in front of ten people and seven of them got stuck at the same step, that finding survives every rewrite. This is the expensive part of product work and the prototype did it cheaply.

Some integration wiring. The shape of a third-party call — which endpoint, which fields, what the response looks like — is often reusable even when the surrounding code is not.

What does not survive is the layer underneath, and it is worth being specific about why, because "it needs to be rebuilt properly" is the kind of sentence that should make you ask for detail.

Steel scaffolding close up, temporary support that has to come off before use

What gets rebuilt, and why

Authentication and authorisation

Authentication — proving who someone is — is usually fine. The prototype wired up a managed provider and that provider is doing the hard part.

Authorisation is the problem. In generated apps, the check for whether this user is allowed to see this record tends to live in the component that renders it. A hidden button is not a permission. If the API route will return the record to anyone who asks for it by ID, the record is public, and it does not matter what the interface shows.

Rebuilding this means the ownership check moves to the data layer, so that it applies to every path that can reach a row, including the ones nobody has written yet. The same goes for roles. Real products need more than "user" and "admin": an owner who can delete the account, an accountant who can see invoices but not change permissions, an invited member with read access to one project. That That matrix has to exist somewhere deliberate.

Production also grows an admin surface the prototype never had. GeoTagImg switches daily and batch limits, coupons and analytics IDs from a backend panel rather than a redeploy, which is the kind of thing nobody asks for until the first time they need it at short notice.

The data model

Prototype schemas grow by accretion. A field is added when a screen needs it, denormalised because that was quicker, and typed loosely because the data was made up.

Production schemas get designed once around the questions the business will ask. Which things are entities and which are attributes. Where the foreign keys go, and whether a delete cascades or is refused. Which columns are indexed, because a query that is instant over 40 demo rows is not instant over 400,000. Whether money is stored as an integer count of minor units rather than a float — the kind of decision that is trivial before launch and a data-repair project after it.

Whether records are deleted at all is a design decision too. Most business software needs an audit trail more than it needs a delete. When we built the invoicing platform in our HisaabKar case study, the accounting rules — payments clearing the oldest invoice first, stock recosted on every invoice edit, every change written to an audit log — are not features bolted on top of a schema. They are the reason the schema looks the way it does. No prototype arrives at that shape by itself, because a prototype is never asked to be correct twice.

Multi-tenancy

This is the single largest rebuild in most SaaS projects, and it is also the one people most often assume is a small change.

Multi-tenancy means every row knows which customer it belongs to, and every query is constrained by that fact — not by convention or by a filter someone remembered to add, but structurally, so that forgetting is not possible. It reaches into authentication, the schema, every API route, background jobs, exports, search, file storage and the admin tooling.

Generated code on a display, the part of a prototype that gets rewritten

A prototype built for one organisation has none of this, and retrofitting it is not a migration. It is a redesign that touches nearly every file. If you know you are building multi-tenant software, this alone is a strong argument for a clean rebuild rather than an incremental repair.

Migrations

Prototypes change the database by changing the database. There is no record of what changed, no way to apply the same change to a second environment, and no way back.

Production needs versioned, reversible migrations checked into the repository and applied on deploy. Cheap to set up; expensive to retrofit once you have live data, because the first migration has to reconcile a hand-edited schema with one that is now defined in code.

Validation and error handling

Client-side validation is a courtesy to the user. It is not a control, because anyone can send a request that never touches your form.

The rebuild puts a schema on the server for every input, shared with the client so the rules are declared once. Then it decides what an error actually does: what the user is told, what gets logged, whether the operation is retried, and whether a partial failure leaves the database in a state that makes sense. A prototype that has only ever seen the happy path has no answer to "what happens when the payment provider times out after taking the money", and that question has to have an answer before you take a payment.

Tests

Generated code rarely comes with meaningful tests, and adding them later is not about coverage numbers. It is about being able to change things.

The tests worth writing first protect money and access: permission boundaries, pricing and tax arithmetic, state transitions, and the paths a user takes to pay you. Without them every change is a gamble, and a feature in month six costs several times what it did in month one.

Security

The prototype's job was to work. Security is the list of things that were not its job.

Rate limiting on anything that sends an email or costs money. Secrets in environment variables rather than in the client bundle. Sensible content-security and transport headers. File uploads checked for type and size, stored somewhere that is not your application server. Dependencies audited. Sessions that expire. The OWASP Top Ten is the plain-language version of this list, and most of it is unglamorous configuration rather than engineering.

Prototypes also leak keys into the browser more often than anyone expects, because the fastest way to make a third-party call work is to make it from the client. Treat any key that has been in a client bundle as public and rotate it.

Deployment, CI and observability

A prototype deploys when you press a button in the tool that built it. Production needs a pipeline: type checking, tests and a build on every push, a preview environment for review, a repeatable release, and a way back when a release is wrong.

It also needs to tell you when it breaks: error tracking with stack traces, uptime checks on the paths that matter, searchable logs, and backups someone has actually restored from. Until that exists, your monitoring is your customers, and they report slowly and only sometimes.

Prototype assumption versus production requirement

LayerWhat the prototype doesWhat production requires
AuthorisationHides UI the user should not seeOwnership enforced at the data layer, on every path
SchemaGrown per screen, loosely typedDesigned around queries, indexed, constrained
TenancyOne implied organisationTenant on every row and every query
Schema changesEdited in placeVersioned, reversible migrations in the repo
ValidationIn the form componentServer-side schema, shared with the client
FailureA toast, or silenceDefined behaviour, logged, retried or rolled back
TestsNoneCoverage of permissions, money and state changes
ReleaseA button in the builderCI, preview environments, rollback
VisibilityNoneError tracking, uptime checks, restored backups

What actually drives the cost

There is no useful price list for this, and anyone who quotes you one before looking at the app is quoting a different project. What there is, is a short list of things that move the number, roughly in order of impact.

Whether it is multi-tenant. Single-organisation internal tool versus a product many companies sign into. This is the biggest single fork in the road.

The size of the data model. Not screen count — entity count, and how tangled the relationships are. Ten well-separated entities is a smaller job than six with circular dependencies.

Live data and live users. A prototype with no users can be replaced. A prototype with paying customers needs a migration plan, a cutover, and a rollback, and that is a project of its own.

Integrations. Each external system carries its own failure modes, sandbox, credentials and support ticket queue. Payments and anything involving a webhook are heavier than the interface suggests, because you are now responsible for events arriving twice, out of order, or not at all.

Regulatory weight. Health, financial or children's data changes what "done" means — data residency, retention rules, audit logs, access reviews. Be upfront about this in the first conversation, because it is the fastest way to make an estimate wrong.

Real-time and background work. Live updates, scheduled jobs, queues and long-running tasks each add infrastructure that a request-response prototype does not have.

How much of the interface is worth keeping. Ironically the cheapest variable, and the one people ask about first.

As a way of reasoning rather than a quote: the closer your app sits to "one company, simple data, no money changing hands", the more of the prototype survives and the smaller the job. The closer it sits to "many companies, money, integrations, existing users", the more the prototype functions as a specification and the more the rebuild resembles a normal custom software project that happens to start with an unusually clear brief. The part after launch, when the thing simply has to keep working, is software development rather than delivery.

How to hand a prototype over so less of it is wasted

A few things you can do before you talk to a development team that genuinely reduce the work.

Get the code out of the builder and into your own Git repository, with history if the tool allows. Export the data, even if it is only test data — the shape tells an engineer more than a description does. Write down what you learned from users, including the features nobody touched, because that is the cheapest scope reduction available. List every third-party account the app talks to. And decide whether your current users are people who would forgive a migration or people who would leave.

Then say what you want to be true in twelve months. An app that will stay a small internal tool deserves a different architecture from one expected to hold thousands of tenants, and the second is only expensive if nobody says so at the start.

The decision rule

Rebuild incrementally if the prototype is single-tenant, the schema roughly matches how you think about the business, and the gaps are auth, validation and deployment. That is a contained piece of work and the existing code is a reasonable base.

Rebuild from a clean architecture if the app must be multi-tenant, if the data model is wrong about something fundamental, or if you are changing both the schema and the permission model. When those two move together, nearly every file moves with them, and porting the interface onto a sound foundation is faster than negotiating with generated code you did not write.

Do neither if the prototype answered its question and the answer was no. That is a good outcome, arrived at cheaply, and it is what prototypes are for. If the answer was that the process is not really yours to own, the build-versus-buy questions are the cheaper next read.

If you have not built the prototype yet and you are weighing tools against a development team, the same reasoning applies one step earlier — we set it out in AI website builder versus professional website development.

Frequently asked questions

Can you take a Lovable or Bolt app straight to production?
Sometimes, for a genuinely simple app with one tenant, no sensitive data and few users. For anything with customer accounts, billing or multi-tenant data, the generated app usually needs its authorisation model, data schema and error handling rebuilt before it is safe to expose to real users.
How much of an AI-built prototype can be reused?
The parts that encode decisions rather than infrastructure. Screen layouts, copy, component structure, the flows you validated with real users and the product scope itself usually carry over. Authentication, the database schema, access control, background jobs and deployment are typically rewritten, because they were generated to demo rather than to hold.
Why does the rebuild cost more than the prototype did?
The prototype priced only the happy path. Production pricing includes authorisation on every query, database migrations, input validation on the server, error handling, tests, CI, monitoring, backups and the work of migrating whatever data and users the prototype already collected without losing any of it.
Is it cheaper to rebuild from scratch than to fix the prototype?
Often, yes, and it is usually faster too. If the schema and the authorisation model both have to change, almost every file changes with them. Starting from a clean architecture and porting the interface and the validated flows across avoids paying twice: once to understand generated code, again to replace it.
Was the AI prototype a waste of money?
No, if it answered a question. A prototype that showed you which features people use, which flows confuse them, or that nobody wants the product at all has done the expensive part of product work cheaply. The waste is building a prototype, learning nothing from it, and then treating it as a foundation.
Share

About the author

Mohsin Ali, CTO at Devfinix

Mohsin Ali

CTO

Devfinix's CTO. Writes about the engineering side of search — rendering, structured data and what crawlers can actually see.

Work with us

Want this done properly?

We build and market the things we write about. Tell us what you're working on and we'll give you a straight answer on how we'd approach it.

Start a Project

Newsletter

One useful email a month

What we learned shipping client work — the fixes that moved numbers and the ones that didn't. No pitches, and we stop the moment you ask.

By subscribing you agree to receive occasional emails from Devfinix. Reply to any email and we will remove you.

Rule the Web!

Request a Web Design and Marketing Proposal.