Rewrite, replace, or repair a mobile app
The rewrite question usually appears when delivery costs rise, releases become difficult, or the current system blocks a required change. Starting fresh can look simpler, but replacement and continued repair both carry engineering, migration, and operating costs.
A replacement must rediscover existing behavior and fund migration while the current application still operates. Continued repair can accumulate cost when a limiting constraint cannot be isolated. The decision should compare evidence from both paths rather than frustration with the codebase.
The decision needs evidence from the current release process, production behavior, architecture, and a representative change. The following framework organizes that evidence.
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 depends on a framework or toolchain that no longer receives security or platform-compatibility updates, the team must either isolate that dependency, migrate it, or replace the affected surface. Verify the actual vendor support status and the application's release constraints before treating age alone as a rewrite signal.
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
A technology becomes an operational constraint when the organization cannot staff it, the build environment cannot be reproduced, or critical dependencies have no supported upgrade path. Measure recruiting, onboarding, and delivery constraints directly; an older language or framework is not sufficient evidence by itself.
The Test Suite Is Nonexistent
An app with no useful automated tests and tightly coupled responsibilities carries a high regression risk, but that does not automatically justify a rewrite. Characterization tests, contract tests at system boundaries, and targeted production telemetry can establish a safety net around the workflows being changed. Compare that incremental cost with a replacement slice before deciding.
Signs You Should Keep Maintaining
Replacement discards behavior encoded in the current system, including edge cases that may not be documented. The case for continued maintenance is strongest when those behaviors can be protected while the architecture improves incrementally.
The Codebase Has Workable Change Boundaries
Architecture labels such as MVVM, Clean Architecture, or MVI do not prove that responsibilities are separated in practice. Incremental change is supported when a representative module can be modified, tested, released, and observed without an uncontrolled change set elsewhere in the system.
The Technology Stack Is Current
A codebase using supported platform APIs and reproducible tools does not need replacement merely because newer UI frameworks exist. Evaluate whether the current stack can meet measured product, accessibility, security, and release requirements before proposing migration.
Users Are Active and Revenue Is Flowing
A ground-up rewrite often competes with feature delivery and operational work. For an active product, compare the cost of parallel development, migration, and dual support with an incremental approach that can continue shipping bounded improvements.
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:
- Identify a self-contained module in the existing app. A settings screen, a profile editor, or a secondary feature flow are good starting points.
- Build the replacement using the new architecture, framework, or technology stack. The replacement lives alongside the old code in the same project.
- Route users to the new module using a feature flag. Start with internal testers, then roll out to a percentage of users.
- Remove the old module once the replacement is stable and validated in production.
- 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.
This approach trades a period of dual architecture for smaller migration units and earlier production feedback. Its risk depends on whether the codebase has stable boundaries, suitable observability, and a reliable way to route and roll back each slice.
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
Measure maintenance cost from actual delivery records: incident work, platform compatibility, dependency upgrades, release effort, and repeated rework associated with known constraints. Build low, expected, and high scenarios across the product's planning horizon, including likely changes in usage and roadmap. Do not infer technical-debt cost from a subjective ideal estimate or project one month forward unchanged.
Cost of a Rewrite
Estimate from observed behavior and thin technical slices, not a universal multiplier. Inventory workflows, integrations, analytics, accessibility, offline states, operational tools, and store configuration. Include dual-running, migration, support, and the opportunity cost of work paused during replacement.
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.
Evidence that supports replacement
A replacement case becomes credible when a thin slice proves that the current stack cannot meet a measured requirement, the limiting constraint cannot be isolated, and the new approach meets that requirement with an operable migration path. “The code is old” and “features feel slow to build” are reasons to investigate, not proof.
Evidence that supports incremental change
Maintenance is favored when the app has a reproducible release, observable production health, seams that let one module change at a time, and active users who depend on behavior a rewrite would need to rediscover. In that case, migrate at boundaries and compare delivery and quality before widening the effort.
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.
DEVSFLOW audits inherited codebases to document the evidence for continued maintenance, staged replacement, or a rewrite. Review the production maintenance scope.