The code was the easy part
There is a moment I keep coming back to.
I was trying to build a calendar. Not a scheduling engine, not a booking system with conflict resolution. A calendar. The thing every app has.
On mobile, it crashed the app. Not a bug I could trace, not an edge case I could reason my way out of. It brought the whole thing down.
I dug for days. I tried every workaround I could find. I wrote to the platform's support. I wrote to other developers who had shipped on the same stack. Nobody had an answer, because there wasn't one.
So we shipped without it. A key feature, one that hundreds of apps do without thinking about it, and we had to go back to the business and say it was not possible.
That is not a sentence you want to say twice.
It was never one day
People imagine the decision to leave no-code as a single moment. A crash, a bill, a founder banging the table. It was not that. It was five constraints arriving at the same time.
Mobile. The product lives as a web app and as a native mobile app. What the platform allowed us to do natively was limited, and performance moved depending on the device in the user's hand. The experience was degrading and we could not stop it from where we stood.
Features. The calendar was the clearest case, but it was not the only one. Things that should be ordinary became negotiations.
Cost. The bill was not unbearable. It was visible. And once you look at it, you notice you have no lever on it. Owning the stack means owning the ability to make it cheaper.
The roadmap that was not ours. We started doubting whether the platform would ship what developers needed, fast enough, to let us build what we wanted to build.
Ownership. When your code is yours, you own an asset. That matters to you, and it matters to anyone looking at the company from the outside.
No single one of these justifies rebuilding a live product. Together they do.
The tool did not get worse. The line moved.
I spent six years in Bubble. I will defend it, and I want to be precise about why.
It is fast. The visual editor is genuinely good, the database is simple to reason about, and when you know the tool you can go from an idea to something in front of users in a day. You can find a bug and fix it in two minutes. That speed is not a marketing claim, it is real, and it is why we built there in the first place.
The argument for no-code was always speed. That argument just lost its edge, because agent-assisted coding arrived and took it.
That is the honest version of what happened to us. Bubble did not get worse. The alternative got faster, and once the alternative is as fast, everything else in the comparison starts to matter: performance, ownership, cost, and how far you can go before the tool says no.
When to go
We went before the summer, and that was a deliberate choice.
Most products have a season where activity dips. That window is the one thing you cannot manufacture, and it is worth waiting for. It gives the team room to do the work properly rather than in the gaps between fires.
One caveat, because this is where migrations go wrong. We were not refactoring for the sake of refactoring. There was a reason behind each part of it: performance, control of cost, ownership of the code, and the ability to build things we could not build before. If you cannot name yours, wait.
What it actually costs
This is the section nobody writes.
You change your team's philosophy. No-code builders are not code builders. It is not that one is better, it is that the reflexes are different, and you have to accept that transition rather than pretend it does not exist.
You change how you test. Not fundamentally, but enough that the old habits do not carry over.
You lose velocity on the small things. A fix that took two minutes in Bubble can take fifteen. The agent sometimes goes in circles. There is a deploy, a pipeline, a check.
Here is the honest counterweight: your user does not care whether you deployed in two minutes or in fifteen. What you gain in exchange is process, cleanliness, and control over what actually ships. And on everything that is not a two-minute fix, working with agents gives you a velocity at least equal to no-code, usually better.
That trade is worth making. It is still a trade.
Everything that does not have a screen
Here is the trap, and it is the one I would warn a founder about first.
When you rebuild a product, you think about the product. The screens, the flows, the things a user can see and click. Those get tested, because someone opens them and looks.
Everything else moves too, and none of it has a screen. Nobody notices when it breaks. That is exactly what makes it expensive: you do not find out on the day you ship, you find out three weeks later, and by then the cost is already paid.
Here is the surface area people forget.
Measurement. Your product analytics events, with their exact names, because renaming them quietly ends your historical data. Your advertising pixels and conversion APIs. Your UTM handling and attribution. Your consent banner, and the fact that tracking actually respects what the user chose. Break any of this and the company keeps spending on acquisition while flying blind, and it looks fine from the outside the whole time.
Before you dismantle anything, extract the tracking plan. In most companies it is not written down anywhere. It lives inside the old tool, and it leaves with it.
Anything that sends. Transactional emails first: sign-up, confirmation, password reset, invoices, notifications. In a no-code stack these often live inside the platform, which means the templates, the branding, the variables and the sending domain all go with it. Then the part people discover too late: sending reputation. New provider, new domain or new IP, no history, and your password resets land in spam. Check SPF, DKIM and DMARC before you switch, not after.
Mobile push is its own trap. Tokens and certificates are tied to the app identity. Change the wrong thing and you lose your entire push audience in one release.
Accounts and money. Migrating users means migrating hashed passwords and sessions, because you do not have anyone's password in clear text and you should not want it. Social login means new redirect URIs. Payments mean subscriptions already running, webhooks pointing at an old URL, and invoice numbering that has to continue rather than restart, which is an accounting question before it is a technical one.
And one product decision hiding in there: on switch day, does everyone get logged out? Decide it, do not discover it.
Links, and the ones already in the wild. URLs you change are URLs you lose, so redirects are not optional. Sitemap, canonical tags, robots. And every link already sent in an email, posted somewhere, or opened as a mobile deep link has to keep landing on something.
Mobile adds a constraint nothing else has: you cannot ship a native app on your own schedule. Store review takes days and can say no. And after release you still have old versions in circulation for months, because a large share of users never update. Your backend serves both, whether you planned for it or not. Forced update is something you build before you need it.
The people who are not your users. The internal back office has an ops team behind it and nobody advocates for them. Support tools carry conversation history keyed on user identifiers. Outbound integrations, automations and webhooks feed other teams' work. Somewhere there is a report someone opens every Monday morning, and it will break without a sound.
The paperwork. Terms and privacy policy usually name your subprocessors. New stack means new subprocessors, which means those documents are now wrong. Data export and deletion have to keep working, because someone can ask tomorrow.
And the one that catches everyone. No-code platforms give you a bit of monitoring for free, so you never had to think about it. In code you start from nothing, and monitoring is the sort of thing that gets pushed to the end and then forgotten. Put it in before the switch, not after. The whole point is to learn about a production problem from a dashboard rather than from an angry user.
None of this is glamorous, and none of it is optional. Make the list before you start. Whatever is not on the list will not be tested, and whatever is not tested will fail quietly.
The part nobody writes about
Five weeks, almost continuously. Web app, native mobile, no service interruption.
The code was the easy part.
The hard part was QA, and I mean something specific by that. In a migration, QA is not a step at the end. It is a state you hold from the first day to the last, and it is the thing that decides whether your users notice anything at all.
One scenario per user journey is the floor, not the ceiling. Testing one path end to end is good. It is not enough. You need the list of journeys, written down, before you start.
Anything with an algorithm needs its own scenarios. One per meaningful set of variables. You are not testing that it works. You are testing that it does not block on any combination someone can actually produce.
Data formats break silently. Dates above all. ISO formats are where things go wrong without anyone noticing, which is exactly the kind of failure that costs the most.
Test against something that looks like production. This is the one I would put first if I could only keep one. In most companies the development database looks nothing like the real one. It is smaller, cleaner, faster. So everything works, and you feel good, and then you ship and discover what real volume does to a page you paginated badly. If you want to know whether your product works, you have to put it under production conditions. Otherwise you are not testing your product, you are testing a demo of it.
Retest everything after every fix. A journey that was green on Monday is not green on Friday. Someone touched the code in between. Go back to the scenarios and run them again, all of them, every time.
None of this is clever. It is rigour, and rigour is expensive because it requires preparation before and discipline after. Writing usable QA scenarios is real work. Holding them when the calendar is pushing you is harder.
The principle underneath is simple. We take the hits so the user does not. A test costs almost nothing. A user finding your bug costs a great deal more, and you do not get to choose when they find it.
What I actually did
I should be precise here, because the interesting part is not the part people expect.
I did not write most of the migration. A developer did that.
What I held was everything around it. The product scoping. Tickets specified so that an agent could not reasonably misread them. A framework, guidelines, a set of practices that everyone worked inside. A repository architecture fragmented enough that several agents could work in parallel without contradicting each other in the code. And then QA, from the first slice to production.
That is the case for the role, and it is why I think it matters.
A team that is migrating does not need one more developer. It has developers. What it usually does not have is one person holding the whole loop: the person who decides what gets built, writes it down so it cannot be misread, watches what comes back, and refuses to trust a green light nobody earned.
When the team is small, that person builds as well. When the team is larger, that person supports the developers and spends the freed time on the thing everyone else deprioritises, which is proof.
Either way it is one role, and it is the one that decides whether the migration is a success or a story you tell carefully.
Where it landed
We finished it. Web app, native mobile, no interruption of service, five weeks.
Not because we wrote code quickly. Because we knew what we were building, we wrote it down in a way an agent could not misread, and we refused to believe anything we had not seen work under real conditions.
If you are looking at your own platform and wondering whether it is your turn, that is the honest test. Not whether no-code is good enough. Whether you can still build what you need to build, and whether you can prove it works when it matters.
If it is your turn
Start with the list. Write down everything in your product that does not have a screen: the tracking, the emails, the payments, the links already out in the world, the reports nobody owns. That list will tell you more about the size of the job than any technical audit will.
The rest of how I work is in a playbook. Seventeen chapters, free, no email required. Specs an agent cannot misread, QA you can hold when the calendar is pushing, and the discipline that makes building with agents safe rather than merely fast.
And if you are the one who has to run the migration, a few questions will tell us both whether it is worth talking. I will say so honestly if it is not.
Keep in touch
Off Market sends you the hidden product builder roles founders fill quietly, before they ever reach a job board. One email, unsubscribe anytime.