AIGuide
daLæs på danskRewrite or Refactor Your Vibe-Coded App? A Decision Guide
Should you rewrite or refactor your vibe-coded app? Six signals, a five-step process and a rule of thumb for picking the path that costs less over a year.

Freelance full-stack developer
- Published
- Reading time
- 13 min
In this post9
Whether you should rewrite or refactor your vibe-coded app depends less on how messy the code looks and more on two questions: is the data model sound, and can you change one feature without breaking two others? If the foundation holds, refactoring is almost always the cheaper path. If it doesn't, a rewrite is coming sooner or later, and early is cheapest.
I'm a freelance developer based in Denmark, and I get paid for both kinds of work, so factor that in. The criteria below are the ones I use, written so you can apply them without reading a line of code.
The short answer: refactor or rewrite?
| Refactor | Rewrite | |
|---|---|---|
| Data model | Tables and relationships match how the business works | The same data lives in several places, or everything is crammed into a few tables |
| Making changes | A fix lands where you expect it | Every fix breaks something somewhere else |
| Security | Problems are local, such as missing access rules or keys in the frontend | Access control and business rules only exist in the browser |
| Codebase | Recognizable structure with some duplication | The same logic exists in many slightly different versions |
| Next 12 months | More screens and smaller features | Subscriptions, roles, integrations or multiple customers in one system |
| Users and data | Paying users and data you can't afford to lose | Few or no users yet |
My rule of thumb: if the data model is sound, I refactor, even when the rest is a mess. If the data model is wrong and the product needs to grow, I rewrite, and the fewer users you have, the cheaper that is. If the signals point both ways, the answer is usually a gradual replacement.
If you haven't shipped to real users yet, start with my guide to taking a vibe-coded app to production. This post picks up where that one stops: what to do when the code can't carry what comes next.
Rescue, refactor, rewrite: what the words mean here
Refactoring means restructuring code without changing what it does. A rescue is broader: you keep the codebase, close the security holes, add automated tests around the flows that matter and refactor the worst parts. The app stays live the whole time.
A rewrite means building the product again in a new codebase, typically on an established framework such as Laravel or Next.js, and moving users and data across once it's ready. The prototype isn't wasted. It becomes the specification, because every screen, flow and rule you've validated is right there in it.
There's also a middle path that founders rarely consider. You build a new backend next to the old one and move one capability at a time, say authentication first and billing next. Martin Fowler calls this the strangler fig pattern. It's slower than a clean rewrite, but the product keeps working throughout, and you can stop as soon as what's left is good enough.
Six signals that decide it
Work through them in order. The first four are about the code. The last two are about your business.
The data model
The data model is how your app stores information: which tables exist and how they relate to each other. It's the most important signal because everything else sits on top of it. A screen can be rebuilt in a day or two. A flawed data model leaks into every query, report and integration you'll ever build.
Typical warning signs: a customer's name stored on both the order and the customer record, and now different in each; whole objects saved as a blob of text in a single field instead of proper columns; or no table at all for something the business revolves around, like subscriptions or teams. AI builders create the data model one prompt at a time, and nobody ever drew the whole picture.
You can fix a data model without a rewrite, but it means migrating data and updating every piece of code that touches those tables. When the problem sits at the core of the product, that's usually where rewriting becomes the cheaper option.
Whether changes land where you expect
Ask for something small, like a new field on a form, and watch what happens. In healthy code, one or two places change. In code that grew prompt by prompt, the same logic often exists in several variants, and the AI tool only updates some of them.
That's the familiar prompt loop: fix one bug, get two new ones. Refactoring and tests can break the loop if there's a reasonable structure underneath. If there's no structure to recognize, a developer has to understand and rewrite most of it anyway, so you're close to a rewrite whatever you call it. I've listed the other warning signs in when to stop prompting and hire a developer.
Where the security holes sit
Assume an AI-built app has security issues. When Veracode tested code from more than 100 language models, 45% of the samples introduced OWASP Top 10 vulnerabilities, the best-known list of common web security flaws. Holes are expected, and on their own they're not a reason to rewrite.
What matters is where they are. Local problems can be patched in place: a Supabase table without Row Level Security, an API key shipped in frontend code, a form that trusts whatever it receives. Supabase's own docs warn that a table without RLS can be read and written through the API. That needs fixing today, but it's a contained job. If you're on Lovable, run through my Lovable and Supabase security checklist first.
Structural problems are harder. If code in the browser decides whether a user may see an invoice or change a price, that logic has to move to a server. In a small app that's a clean-up. In a large one it's effectively a new backend. I cover the most common vibe coding security issues in a separate post.
Whether the code runs outside the tool
Most AI builders let you export the code or sync it to GitHub. That's not the same as being able to run it anywhere else. Check for dependencies that only work inside the tool, whether environment variables and keys are documented, and whether a developer could start the app on their own machine from a README.
If the code can be moved and run, a rescue is realistic. If the app is tied to the tool's own hosting or built-in services in ways you can't unpick, you're already halfway into a rewrite.
What the app needs to do next year
Look 12 months ahead. If the roadmap is mostly more screens and small improvements, almost any codebase can carry it after a clean-up. If it includes subscription billing, roles and permissions, integrations with other systems or multi-tenancy (several customer organizations in one system), it asks things of the foundation that prototypes are rarely built for.
That's where a rewrite tends to pay for itself. You spend more now, and every feature after that gets cheaper because nobody is working around old decisions.
Real users and real data
With no users or only a handful, a rewrite is relatively cheap: there's no data to migrate and nobody to notice the switch. With paying customers, a rewrite also has to cover data migration, moving accounts and a cutover plan. The more users you have, the more I lean toward a rescue or a gradual replacement, even when the code is poor.
What each path costs over 12 months
The first invoice is the smallest part of the math. Compare what each path costs over the next year, including the development you'd be doing anyway.
A rescue is cheaper upfront and starts sooner. If the structure stays weak, though, you pay an ongoing tax: each new feature takes longer and more bugs slip through. That tax is small in decent code and large in messy code.
A rewrite costs more upfront. You pay for new code, data migration, testing and a period where two versions have to stay alive. Afterwards, building is cheaper, and it's far easier to hand a standard Laravel or Next.js app to a new developer than a codebase nobody designed.
As a rough guide, a thorough rescue costs a fraction of rewriting the same app. If that rescue turns out to be the first of many, the math flips quickly.
One thing has changed: when an experienced developer uses AI tools, the typing goes faster. Scoping, data migration and testing still take the time they always did. Rewrites are cheaper than they used to be, but they're not free.
A five-step decision process
- Pause new features for a short while. Every feature you prompt in now will need cleaning up or rebuilding later. Waiting a couple of weeks costs less than building more on a foundation you might replace.
- Get the code into a repository you own. Sync or export it to a GitHub account that belongs to your company, not to a contractor or a personal account. Then any developer can read it, and you're not tied to one tool.
- Commission a scoped code review. Ask a developer to assess the data model, security, structure, dependencies and whether the app runs locally. For a typical prototype that's days of work, not weeks. Insist on a written recommendation with reasons.
- Price both paths over 12 months. Take your feature list for the next year and get one estimate for a rescue plus that roadmap, and one for a rewrite plus the same roadmap.
- Decide how you'll switch, not just what. If you rescue, fix security first, then add tests, then restructure. If you rewrite, choose between a single cutover and a piece-by-piece migration, and plan how users and data move.
If you rewrite, carry the prototype forward
The classic case against rewrites is Joel Spolsky's essay from 2000, which calls starting from scratch the worst strategic mistake a software company can make. His argument: old code holds years of real-world bug fixes that vanish when you start over. That still applies to a system that's been in production for a decade. A prototype built in a few weeks with AI carries far less hidden knowledge, and what it does carry is visible right there in the product.
To keep that knowledge:
- Treat the prototype as the spec. Walk through every screen and flow, and write down what stays and what goes. How users actually behave in the prototype is worth more than any requirements document.
- Pick a boring, well-documented stack. Laravel and Next.js both have large communities and plenty of developers, so you're not dependent on one person afterwards. I compare them in Laravel vs Next.js.
- Freeze the scope. New features wait until the new version is live, or the rewrite never ends.
- Plan the data migration from day one. Test it against a copy of real data, not sample data.
- Fix data location while you're at it. If your users are in the EU, a rewrite is the natural moment to choose EU hosting and to know exactly where personal data is stored and processed.
When to spend money on neither
Some apps shouldn't be rescued or rewritten. If you don't have paying users yet and you're still working out what the product is, keep prompting. Code quality isn't your bottleneck. The same goes if you're about to pivot: there's no point polishing an app you'll throw away in three months.
An internal tool for a handful of colleagues can also live with messy code as long as it works. If it handles personal data or payments, close the security holes anyway, because with European users a leak is a legal matter, not only an embarrassment.
And if you already have a developer who knows the codebase, giving them time to clean it up is often a better deal than bringing in an outsider, me included.
Next steps
Before you choose between refactoring and rewriting
- The code lives in a repository your company owns.
- Security holes that could leak data are closed, whatever you decide next.
- You have a list of what the app must do over the next 12 months.
- You know how many users and how much data a rewrite would have to move.
- A developer has reviewed the data model and given a written recommendation.
- You have estimates for both paths over 12 months.
- You've decided how the switch happens: step-by-step refactoring, gradual replacement or a single cutover.
If you rescue the app, the ongoing work matters more than the clean-up itself, so read up on what maintaining AI-generated code costs over time. If you'd like help with the assessment or the work itself, here's how I approach maintenance and development of existing apps.
Frequently asked questions
Can I refactor the app myself with Cursor or Claude Code?
Partly, and it can save time, but only if someone is steering. AI coding tools are good at contained changes, like merging duplicated logic or splitting large files. Without automated tests, though, you won't see what breaks along the way. Write tests around the most important flows first, and have a developer review the changes before they go live.
Do I need to move off Supabase if I rewrite?
Not necessarily. Supabase runs on Postgres, a standard database that both Laravel and Next.js can connect to directly. Keeping the database, cleaning up the tables and moving business rules into a proper backend is often the sensible route. Whether to leave entirely depends on cost, where your data needs to be hosted and how many Supabase-specific services you rely on.
Will my users lose their logins in a rewrite?
Not if the switch is planned. Accounts and data can usually move across, but authentication needs the most care, because passwords are stored as one-way hashes that the new system must be able to verify. The fallback is asking users to set a new password on their first login. Decide on the approach upfront and test it with a copy of real data.
Is an exposed database a GDPR breach?
If it exposed personal data of people in the EU, it may well count as a personal data breach. Under Article 33 GDPR, the controller must notify the supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware of it, unless the breach is unlikely to put people's rights at risk. This isn't legal advice, so check with a lawyer or your data protection officer.