When to Rewrite vs. Maintain a Legacy Mobile App

The rewrite question comes up in every legacy mobile app eventually. The codebase is aging, the original team is gone, new features take three times longer than they should, and someone suggests starting fresh. It is a tempting idea. It is also one of the most expensive decisions you can make, and getting it wrong in either direction costs real money and time.

Rewriting when you should have maintained means months of development with no new features for users, missed market opportunities, and a high risk of the new version shipping with fewer capabilities than the old one. Maintaining when you should have rewritten means throwing good money after bad, fighting an architecture that actively resists change, and watching your best engineers leave because they are tired of patching a system that should not exist anymore.

Here is the framework we use when advising teams on this decision.

Signs the App Needs a Rewrite

Not every painful codebase needs a rewrite. Pain alone is not a sufficient signal. But there are specific technical and organizational indicators that point clearly toward starting over.

The Framework Is End-of-Life

If the app is built on a framework or platform that is no longer supported, maintaining it becomes increasingly expensive. Examples include apps built with Xamarin.Forms (replaced by .NET MAUI), early React Native versions before the New Architecture, or Cordova-based apps that cannot meet current platform requirements. When the framework itself is not receiving security patches or compatibility updates, every OS release becomes a crisis.

Architecture Rot Has Gone Too Far

Architecture rot is the gradual accumulation of shortcuts, workarounds, and layering violations that make the codebase increasingly difficult to change. Warning signs include: circular dependencies between modules, God classes with thousands of lines that handle unrelated responsibilities, state management spread across dozens of singletons, and a dependency graph so tangled that changing one screen can break three others.

The critical question is whether the architecture can be improved incrementally. If you can refactor one module at a time without touching everything else, the architecture is salvageable. If every change requires understanding and modifying the entire system, you have passed the point where incremental improvement is practical.

You Cannot Hire for the Technology

If the app is written in Objective-C with no Swift, or uses a niche cross-platform framework that few developers know, your hiring pool shrinks dramatically. Maintenance costs rise because specialized talent commands higher rates. Onboarding takes longer because new developers need to learn an unfamiliar technology stack. This is a business problem as much as a technical one.

The Test Suite Is Nonexistent

An app with zero automated tests and no clear separation of concerns cannot be safely changed. Every modification is a gamble because there is no way to verify that existing functionality still works. If the app also lacks crash reporting and analytics, you are operating completely blind. Adding tests retroactively to a tightly coupled codebase is sometimes more effort than rebuilding with testability in mind from the start.

Signs You Should Keep Maintaining

Rewrites fail more often than they succeed. Joel Spolsky called rewriting from scratch "the single worst strategic mistake that any software company can make." While that is an overstatement, the bias should be toward maintenance unless the rewrite case is overwhelming.

The Core Architecture Is Sound

If the app follows a recognizable architecture pattern (MVVM, Clean Architecture, MVI) and the layers are reasonably well separated, the codebase can be improved incrementally. Ugly code that is well structured is dramatically easier to fix than pretty code with no structure.

The Technology Stack Is Current

An app written in Swift with UIKit or Kotlin with Jetpack components is on a supported, actively maintained technology stack. The fact that newer alternatives exist (SwiftUI, Compose) does not mean the current stack is obsolete. UIKit and the Android View system will be supported for many years. Rewriting to adopt the newest UI framework is rarely justified by business value alone.

Users Are Active and Revenue Is Flowing

A rewrite freezes feature development for months. If the app has active users and generates revenue, the opportunity cost of going dark on features is substantial. Competitors do not pause while you rewrite. Maintenance lets you continue shipping improvements while addressing technical debt incrementally.

The Strangler Fig Pattern

When the answer is not clearly "rewrite" or "maintain," the strangler fig pattern offers a middle path. Named after the strangler fig tree that grows around and eventually replaces its host tree, this approach lets you rebuild the app piece by piece while keeping the existing app running in production.

The pattern works like this:

  1. Identify a self-contained module in the existing app. A settings screen, a profile editor, or a secondary feature flow are good starting points.
  2. Build the replacement using the new architecture, framework, or technology stack. The replacement lives alongside the old code in the same project.
  3. Route users to the new module using a feature flag. Start with internal testers, then roll out to a percentage of users.
  4. Remove the old module once the replacement is stable and validated in production.
  5. Repeat with the next module.

On Android, this is particularly practical because you can introduce Jetpack Compose screens inside an existing View-based app using ComposeView. Each new screen can be Compose-based while existing screens remain untouched. On iOS, SwiftUI views can be wrapped in UIHostingController and presented within a UIKit navigation stack.

The strangler fig approach takes longer than a ground-up rewrite but carries far less risk. You ship continuously, validate each piece in production, and can pause or reprioritize at any point without losing progress.

Building the Business Case

Technical arguments alone rarely win the rewrite vs. maintain debate. Decision makers need to see the cost and timeline comparison in concrete terms.

Cost of Continued Maintenance

Calculate the current cost of maintaining the app. Include developer hours spent on bug fixes, OS compatibility updates, dependency upgrades, and the extra time required for new features due to technical debt. If a feature that should take one sprint consistently takes three, the overhead is quantifiable. Multiply the monthly maintenance cost by 24 months to get a two-year projection.

Cost of a Rewrite

Estimate the rewrite honestly. Rewrites take longer than expected because they need to replicate every feature of the existing app, including the ones nobody remembers building. A common heuristic: take your initial estimate and multiply by 2.5. Include the opportunity cost of features not shipped during the rewrite period.

Risk Assessment

The rewrite carries execution risk (will it actually be better?), schedule risk (will it take longer than planned?), and feature parity risk (will users lose functionality they depend on?). Maintenance carries different risks: escalating costs, inability to meet future platform requirements, and developer attrition. Lay out both risk profiles clearly.

Scenario: When the Rewrite Was Right

A retail app built on Cordova in 2017 had accumulated performance issues that no amount of optimization could resolve. Page transitions took 800ms or more. The app could not use the device camera with acceptable quality. Push notification reliability was below 70%. The app was rebuilt in native Swift and Kotlin over five months. Post-launch metrics showed a 3x improvement in user session length and a 40% increase in conversion rate. The performance ceiling of the hybrid framework was the binding constraint, and no amount of maintenance could fix it.

Scenario: When Maintenance Won

A healthcare app built in Objective-C with 200,000 active users was proposed for a complete Swift rewrite. The codebase was old but well structured, with clear MVC separation and comprehensive unit tests. The rewrite estimate was eight months with a team of four. Instead, the team adopted a strangler fig approach: new features were built in Swift, and existing Objective-C modules were migrated one at a time during regular maintenance cycles. After 18 months, 60% of the codebase was Swift, zero features were lost during the transition, and the app shipped updates continuously throughout the process. The total cost was lower than the projected rewrite, spread over a longer period, and carried near-zero risk of regression.

There is no universal answer. But with a structured framework, honest cost analysis, and a clear understanding of both the risks and the rewards, you can make the right call for your specific situation.

Not sure whether your legacy app needs a rewrite or ongoing maintenance? DEVSFLOW Maintenance can audit your codebase and give you an honest assessment with a concrete plan forward. Reach out to our team for a technical evaluation.