How much does it cost to migrate an app to Flutter?

The cost of migrating a native app to Flutter comes down to three things: a one-time setup cost for the native-Flutter plumbing, a per-screen cost that depends mostly on how connected each screen is, and the cost of running both technologies side by side until the migration ends. Flutter's savings - one codebase and one team instead of two - only fully show up after the exit, so the real question is not only "how much", but also "how long until it pays off".

There's no honest single number for "migrating an app to Flutter". Two apps with the same number of screens can differ a lot in cost, depending on how many screens are self-contained and how many are tangled with native SDKs. This page describes how we estimate it on our projects with Converge: a tool that reads your Android and iOS code and turns it into a migration plan with a per-screen estimate.

What drives the cost of migrating to Flutter

One-time add-to-app setup cost

Before the first Flutter screen ships, someone has to build what every later screen relies on: the module in both native builds, engine management, navigation in both directions, shared state across engines, typed native-Flutter contracts, the Flutter version of the design system, and CI. None of it is visible to the business, so explain up front why the first screen takes longer than the next ones. This is the part a framework reduces the most - navigation, state sharing and engine management are what every add-to-app team ends up building by hand, which is exactly why we built Inlay. We heavily recommend not rushing through this period and do the initial setup with help of an experienced Flutter engineer - the decisions taken here can really speed up or slow down all further development.

Cost per migrated screen

Each migrated screen costs the UI rewrite (the part people usually estimate) plus the boundary work (the part they usually don't): every piece of data the screen needs from native, every navigation path in and out, every native SDK it calls. In our experience, a self-contained leaf screen is mostly UI work, while a screen in the middle of a native journey can easily cost a few times more than its UI alone would suggest. That's why the first thing Converge does is map every screen and the navigation between them, so the boundary work is visible before anyone starts estimating.

There is also the cost of matching the existing behavior - rediscovering every edge case, validation, analytics event and accessibility label the native version handles. When the native code is well documented, this is cheap. When it isn't, it can dominate the estimate, as in the "add-to-app will be safer" case from the planning page. Differences between the iOS and Android versions of the same screen are a common source of such surprises, and Converge points them out for every screen.

The cost of running native and Flutter side by side

As long as the app is hybrid, you pay for both worlds. A phased rollout keeps the native screen as a fallback behind a feature flag, which is what you want for risk - but until the flag is removed and the native code deleted, both versions have to be maintained and tested, so set a date for removing the native version when you turn the flag on. Infrastructure is duplicated (see Limitations), builds and CI get slower, and native developers are still needed for the host, the boundary and the SDK integrations until the exit.

How to estimate a Flutter migration screen by screen

We typically estimate per screen, because the differences between screens are bigger than any average would show. For each screen, we look at:

  • UI complexity - how many states, how custom the components are, whether the design system already covers them.
  • Connections to the rest of the app - navigation paths in and out, data passed across, deep links. Each is a contract to specify and maintain.
  • Native dependencies - camera, maps, payments, biometrics, ads. Logic-only SDKs can be wrapped behind a typed API; SDKs whose contract is their own view usually mean embedding, the most expensive case.
  • Platform divergence - if iOS and Android behave differently, someone has to decide which behavior wins, and that is often a product discussion.
  • Knowledge of the existing code - whether anyone still understands what the native screen does.

Going through these by hand works for a few dozen screens. For a large app, it means reading two codebases screen by screen, often written by people who have long left. This is exactly what Converge automates: it reads both codebases, maps every screen and the navigation between them, shows where the platforms differ, and estimates each screen with the reasoning spelled out, so you can check every number instead of trusting an average.

Screen typeTypical examplesWhat dominates the cost
Self-contained leafSettings, profile, FAQ, onboardingUI work
New feature, no native versionA new module or verticalUI and the single entry point
Connected screenLists and details in the middle of a journeyContracts for data and navigation
Native-SDK-heavyCamera, maps, payments, adsWrapping or embedding the SDK
Central hubHome screen, dashboardContracts with everything around it

We deliberately don't put person-day ranges next to these types - they depend too much on the team, the codebase and the design system to be a useful benchmark, which is why Converge estimates your screens from your own code. The order matters as much as the per-screen numbers: migrating a whole journey together often costs less than its screens one by one, because the contracts between them never have to be built. Converge proposes such an order, starting with the least connected screens - see Planning the migration.

How long does a migration to Flutter take?

A migration usually goes through four phases. Their length depends on the app and the team, but the order is the same:

  1. Proof of concept - one or a few screens in production behind a feature flag.
  2. Foundation - the plumbing, the design system in Flutter, CI, and the conventions the team will follow. Partly overlaps with the PoC.
  3. Migration waves - journeys migrated one after another, from the least connected towards the center of the app. The longest phase, and the one where team size changes the timeline the most.
  4. Exit - Flutter takes over the shell and navigation, and the remaining native screens are hosted inside it.

The timeline is also shaped by things outside the code: how many developers can work in Flutter at once, whether the native team keeps shipping features in parallel (it usually does), and how often the business reprioritizes. That last one is why the plan can't be a one-time document.

How Flutter reduces mobile app development costs

The saving comes from writing the UI and business logic once for iOS and Android: every migrated screen stops needing two implementations, two sets of bugs and two review processes. New features built in Flutter from the start are the quickest win, because there is no native version to replace.

That said, the saving is smaller than "half the cost" for most apps. Native SDK integrations, push notifications, widgets and extensions remain native, QA still tests both platforms, and teams need time to ramp up. In practice, the cost curve goes up first, while you pay for the setup and run both technologies, and goes down as the share of Flutter grows and native code is deleted. The bigger the share that ends up in Flutter, and the sooner you exit, the sooner it pays off.

Keeping the migration estimate up to date with Converge

A migration estimate made on day one is usually wrong by month three - the native app keeps changing, priorities shift, and the team learns what the boundary really costs. Because Converge works on the code itself, you can run it regularly and let it adjust the plan as the migration goes, instead of maintaining a spreadsheet by hand. We are also building it to turn the plan into Jira epics and tickets, so the migration lives in the same backlog as the rest of the work.

Privacy Policy

On this page