Stabilize Before You Rewrite: An App-Rescue Playbook
What twelve years of inheriting other people's mobile codebases taught me about the 'just rewrite it' reflex.

Every unstable app I've inherited arrived with the same advice attached — usually from someone who'd never opened the code: just rewrite it.
It's the most expensive wrong answer in mobile development. A rewrite trades a known set of bugs for an unknown one, burns months you usually don't have, and — the part everyone forgets — throws away years of hard-won edge-case handling that lives nowhere except the code you're about to delete. Most of the time, the app doesn't need a rewrite. It needs a mechanic.
I've taken over roughly a dozen unstable or abandoned mobile codebases — some with millions of installs, some left mid-flight by an outgoing team — and stabilized nearly all of them in place. Faster than a rewrite, and without the risk. Here's the playbook I run every time.
1. Diagnose before you touch anything
The strongest urge when you open a janky codebase is to start fixing what you can see. Resist it. The bug you can see is rarely the bug that's hurting users.
When I took over Unified Remote — an Android and iOS remote-control app with over 10 million installs — the app felt sluggish and the frames stuttered, and there were a dozen plausible culprits. Instead of guessing, I profiled: GPU rendering, memory, frame timing. The profiler pointed somewhere specific — live image frames were being decoded and uploaded on the main thread, blocking every frame queued behind them. No amount of intuition-led cleanup would have found that as fast as ten minutes with the right tool.
Profile first. Let the data tell you where the pain actually is. You'll be wrong about your first guess more often than you'd like to admit — I know I am.
2. Kill the worst pain fast — in place
Once you know the real problem, fix that one thing, surgically, without disturbing the surrounding architecture. Early wins buy you trust and time; a three-month refactor with nothing to show buys you neither.
On Unified Remote, the fix that followed the diagnosis was moving bitmap uploads to the GPU on a background thread. Result: 3× faster live-image rendering, with frame times and memory back under Android Vitals limits — and I hadn't rewritten a single feature. (While I was in there, I also took the aging codebase from min API 9 to 14 in under three months and deleted the dead and duplicated code I found along the way. Cleanup, not reconstruction.)
Jirah Parent was another app I inherited unstable. The visible symptom was UI jank; targeted profiling and render-pipeline fixes cleared it in under a month. Not a rewrite — a month of focused, evidence-led changes on the code that was already there.
The pattern: smallest change that removes the biggest pain. Ship it. Repeat.
3. Put boundaries in so it stops regressing
Surgical fixes stop the bleeding. They don't stop the next developer — including future you — from reintroducing the same class of bug. That's an architecture problem, and it's where you invest after the app is stable, not before.
On the Yahoo Fantasy Sports Android app, I owned stability for the Daily Fantasy and later Core Fantasy modules. The screens I inherited mixed business logic straight into the views, and that was why the same bugs kept coming back — there was nowhere clean to put a fix. I led the MVP→MVVM refactor that lifted business logic into a real domain layer, then drove crash and ANR rates down release over release, using Sentry, Embrace, and QA-filed signal to confirm each release actually moved the numbers rather than just felt better.
Notice the order: I earned the right to refactor by stabilizing first. Boundaries are how a fix stays fixed — but you introduce them incrementally, module by module, on a codebase that's already shipping. Never as a big-bang rewrite wearing a refactor's clothes.
4. The pipeline is part of the codebase
Here's the step most engineers skip: a codebase you can't reliably build and ship is unstable, no matter how clean the code reads. If releasing means one person hand-building an APK and dropping it into a chat, you don't have a stable app — you have a stable app and a fragile deployment that will eventually take the app down with it.
At Carewell, a healthcare-workforce app on Android and iOS, the Android pipeline was broken and there was no iOS pipeline at all. I rebuilt the Android one, created the iOS one from zero, moved distribution to Play Store internal-testing, and shepherded the app through review. At SKEDit, I rebuilt a broken CI/CD pipeline and shipped 10+ releases in three months — automating Play Store internal-testing so QA stopped receiving APKs hand-delivered over Slack.
Boring work. It's also the difference between a team that can respond to a production fire within the hour and one that can't respond at all. Fix the pipeline. It's part of the rescue, not a chore you get to afterward.
5. Only now, ask whether you actually need a rewrite
Run the four steps above and something happens: the "obviously doomed" app is stable, shipping predictably, and cheap to change. And the rewrite that felt urgent three months ago turns out to have been the panic talking.
I won't tell you a rewrite is never right. When the platform underneath you is genuinely dead, or the app fundamentally can't support where the product needs to go, replacement is the honest call. But that's a decision you make from stability, with data, having exhausted the cheaper options — not the reflex you reach for on day one because the code is unfamiliar and a little scary.
Unfamiliar and scary is just what someone else's code feels like. It isn't a diagnosis.
The actual principle
Stability isn't a heroic rewrite. It's a process: diagnose with tools, fix the worst pain in place, add boundaries so the fixes hold, make shipping reliable, and reserve rewriting for when you've genuinely earned the conclusion that you need one. Run it in that order and most "unsalvageable" apps turn out to be very salvageable — in weeks, not quarters.
That's the work I do: inheriting mobile codebases other people have given up on, and getting them stable, shippable, and calm again. If you've got one — Android, iOS, or Flutter — that's limping along and someone's already whispered "rewrite," it's worth a second opinion first.
Ramiz Raja is a senior mobile developer and technical lead with 12+ years shipping and rescuing production apps on Android, iOS, and Flutter. More at codebyramiz.com.