Add-to-app is Flutter's official mechanism for embedding a Flutter module inside an existing native iOS or Android application. The host app stays exactly what it is — your Swift or Kotlin codebase, your release process, your users — and Flutter arrives as one compiled module behind it, rendering the screens you choose to give it. Each of those screens is written once and runs on both platforms.

This page is for teams who want Flutter inside the app they already have: a native product nobody is going to rewrite, whose next features keep costing twice because they must be built for iOS and Android separately. If your actual goal is to end up on Flutter entirely, that is a different engagement with the same mechanics — read React Native and native migration instead, which is honest about being a rewrite. Here, nothing gets rewritten: the native app remains the product, and Flutter earns its place one feature at a time.

The engagements we run

  • A pilot feature — one bounded feature built in Flutter and shipped inside both of your native apps, with the integration cost and the payoff measured rather than argued about
  • Feature-parity catch-up — the screen your iOS app has and your Android app doesn't (or the other way round), built once for both instead of a second time for one
  • The new surface — a loyalty program, a booking flow, a chat: a self-contained addition to a mature native product, reaching both platforms on one budget
  • Adoption groundwork — the module scaffolding, router integration, CI wiring, and platform-channel contracts set up properly, so your own engineers ship the features

Who This Is For — and Who Should Migrate Instead

Add-to-app pays for itself under specific conditions, and we would rather name them than sell an integration to a team that needs something else.

Signs add-to-app fits

  • Every roadmap feature is built twice, and the iOS and Android versions of your app have started to drift apart in capability
  • The app is too large or too proven to rewrite, so "just use Flutter" has never been an available answer
  • You want to evaluate Flutter on real production work — one feature, real users, measured — before making any larger commitment
  • Two platform teams are hard to staff evenly, and new surfaces stall on whichever platform is short-handed this quarter

When it is NOT the right call

  • The app is small enough that a fresh Flutter build or a screen-by-screen migration costs less than maintaining a native–Flutter seam — integration has overhead, and a small host cannot amortize it
  • The decision to end up 100% Flutter is already made — then run it as a migration from day one, with a migration map, rather than drifting into one
  • The app is already React Native — embedding a second cross-platform runtime next to the first one compounds the problem; that team's realistic options are staying put or migrating
  • The feature you want is a deep platform capability — a widget-led experience, Watch-first functionality — where Flutter is the wrong tool and we will say so

The honest read: a hybrid app is a permanent seam — two toolchains, two sets of idioms, and a boundary that every engineer on the team has to understand. Add-to-app is worth that cost when the host app is too big to rewrite and the roadmap keeps paying the two-platform tax. If neither is true of your app, one of the neighbouring pages is the better answer, and the first call is where we tell you which.

How Incremental Adoption Runs

The Add-to-App Flow

Step 1

Native App Stays the Product

Your iOS and Android apps keep shipping unchanged — no freeze, no parallel rewrite, no cutover on the horizon

Step 2

Flutter Module Embedded

One Flutter module is wired into both hosts, sharing their navigation, authentication, and analytics through defined contracts

Step 3

Pilot Feature Ships

A bounded feature is built once in Flutter and released inside both apps, with size and startup cost measured before and after

Step 4

Adoption Grows Feature by Feature

Each new surface that lands in the module is one you did not build twice — and each one is a decision, not an obligation

Step 5

You Decide the Endgame

Stay hybrid indefinitely, hand the module to your own team, or convert the momentum into a full migration — every boundary is a stopping point

The flow is deliberately the same machinery our migration service uses — a Flutter module behind a shared router, screens moving one at a time. The difference is the destination: a migration retires the native host at the end, and adoption never has to. That also means adoption converts cleanly into a migration later if the module earns it, with nothing thrown away.

What Add-to-App Actually Demands

One engine, with an owned lifecycle

A Flutter module brings the Flutter engine with it, and the engine is a resource the host app must manage deliberately: pre-warmed so the first Flutter screen opens without a visible spin-up, shared across entry points rather than instantiated per screen, and released when the platform asks for memory back. Getting this wrong is invisible in a demo and obvious in production. It is the first thing we build, not the last thing we tune.

Users do not care which framework rendered the screen they are on, and the navigation must agree: back gestures behaving per platform convention, deep links landing on Flutter screens as reliably as native ones, and state surviving the crossing in both directions. The router contract between host and module is the piece of add-to-app architecture that decides whether the seam is invisible or a permanent source of bugs.

Shared services, borrowed rather than duplicated

Your app already has authentication, analytics, networking, and feature flags. The Flutter module must borrow them across — not grow its own copies, which is how a hybrid app ends up with two sessions, two event schemas, and metrics nobody trusts. Defining those channel contracts precisely is most of the groundwork engagement, and it is work that pays out on every feature that follows.

Two toolchains in one pipeline

After integration, your builds the Flutter module and both native hosts, and the module is versioned against two release trains that will not always move together. We wire the module build into your existing pipeline — cached, reproducible, and owned by your repo rather than by a laptop — because an integration your CI cannot build is not integrated.

A seam your designers can live with

Flutter draws its own pixels, which cuts both ways: it will not inherit your native components, but it will reproduce your design system exactly — once your tokens, typography, and spacing are ported into the module's theme. We do that porting as part of the groundwork, so a user scrolling from a native screen into a Flutter one has no way to tell where the boundary was.

The costs, measured instead of asserted

Embedding Flutter adds real weight: on the order of several megabytes to an Android release and somewhat more on iOS, plus engine startup on first launch of a Flutter screen. The exact numbers depend on your app, which is why the pilot's deliverables include the before-and-after measurements of binary size and startup time — you decide whether to go further with data from your own product, not from a benchmark blog post.

Production Precedent

Add-to-app has been a supported Flutter integration model for years, and its best-known user is Google Pay, which adopted Flutter inside an existing native app with hundreds of millions of users before committing further. The pattern is the one this page describes: embed, ship one surface, measure, then decide. Our own delivery record with it comes from migration work, where the same module-behind-a-router machinery carries whole apps across; adoption uses that machinery with a lighter commitment.

How We Work

Fixed-scope groundwork and pilot. We integrate the module into both hosts, port the design tokens, define the channel contracts, and ship the first feature — a bounded engagement with the measurements as part of the deliverable. Our development process describes how we run scoped work week to week.

Embedded engineers. Our Flutter engineers join your native team, in your repo and your sprints, and build out the module alongside the people who own the host — see team augmentation. This is the natural shape once the pilot has proven out and the module becomes a place where your roadmap regularly lands.

Either way, we send a scoped quote within two business days of understanding the requirements.

What Add-to-App Integration Costs

The groundwork-plus-pilot engagement is quoted after we see the app: the integration cost is driven by the host — its navigation architecture, its build system, how its shared services are exposed — far more than by the pilot feature itself, so a number produced before looking at the codebase would be fiction. As an anchor, a bounded pilot lands well below what a standalone app costs — the published tiers on the Flutter app development page start at $15–30K for a full MVP, and a pilot feature inside an existing host is a fraction of that scope.

For the embedded model, the published team augmentation rate applies: $10–14K per senior engineer per month. And if the roadmap's honest endgame is an app that is entirely Flutter, price it as what it is — a migration, which that page anchors against a full rebuild, not as an adoption that outgrew its name.

Frequently Asked Questions

Common questions from teams considering Flutter inside an existing native app.

Yes — that is precisely what Flutter's add-to-app integration model exists for. A Flutter module is embedded into your existing Swift or Kotlin app, wired into its navigation, authentication, and analytics through platform channels, and renders the screens you choose to build in it. Your app keeps shipping unchanged throughout; the module is added alongside the code you have, not instead of it. Each Flutter screen is written once and runs inside both your iOS and Android apps.
No. Adoption and migration share the same mechanics — a Flutter module behind a shared router — but a migration commits to retiring the native app at the end, and adoption never has to. Every feature boundary is a legitimate stopping point: some products stay hybrid indefinitely with Flutter owning a handful of surfaces, some hand the module to their own team, and some convert the momentum into a full migration once the module has earned it. Nothing built during adoption is thrown away if you later go further.
The Flutter engine and module add real weight — on the order of several megabytes to an Android release build and somewhat more on iOS. The precise number depends on your app and what the module contains, which is why our pilot engagement includes before-and-after measurements of binary size and startup time on your actual product. You make the adoption decision from your own numbers, not from a generic benchmark.
Mechanically it works — Flutter can be embedded into a React Native host the same way as into a fully native one. Strategically it rarely makes sense: you would be running two cross-platform runtimes, two bridges, and three UI idioms in one binary, which compounds the maintenance problem instead of solving it. For a React Native team unhappy with the status quo, the realistic options are staying put or migrating to Flutter screen by screen — and our migration page opens by telling you who should do neither.
Yes. Add-to-app has been a supported Flutter integration model for years, and its best-known adopter is Google Pay, which embedded Flutter inside a native app serving hundreds of millions of users before extending its commitment. The pattern of embedding a module, shipping one surface, measuring, and then deciding is well trodden. The engineering risks that remain are the integration details — engine lifecycle, navigation across the boundary, duplicated services — which is exactly the work a structured groundwork engagement front-loads.
Not for the pilot — we build it, and your team reviews the module boundary rather than the Dart inside it. If Flutter adoption grows, some of your engineers will want to work in the module, and Dart is a small step from Swift or Kotlin: strongly typed, garbage collected, and closer to what they already write than JavaScript would be. The embedded-engineer model exists for exactly this transition — our people build alongside yours until the module is a codebase your team owns rather than one it hosts.

Read the migration page if the destination is all-Flutter, team augmentation for the embedded model, or start from the Flutter app development pillar.