Lessons learned from migrating a native iOS app to Flutter
In this technical retrospective (2022), @PanMan shares practical architectural lessons learned from running, scaling, or migrating production software under lean constraints.
Core Principles for Independent Builders:
Defaulting to simpler architectures (such as monolithic frameworks, SQLite, or managed VPS) prevents early engineering bankruptcy.
Evaluating true compute and egress costs reveals that high cloud bills can often be slashed by 80%+ through judicious re-platforming.
Code you write at 2 AM as a solo engineer must be easy to debug six months later without complex microservice dependencies.
Community Debate Themes:
HN engineers debated the tradeoffs between cloud convenience and raw server economics, database indexing strategies, and resisting premature architectural complexity.
CATEGORY Frugal Engineering →
HISTORICAL ERA Pandemic Bubble (2020–2022)
COMMUNITY SCORE 231 points
TOTAL DISCUSSIONS 141 comments
Tim here from the Flutter team; thanks for the post. There are some good points here: in particular, that no single framework or toolkit is the "holy grail". We all live in a world of trade-offs, and anyone who claims that any single technology is the panacea for all problems is selling a mirage.
I really appreciate the constructive critique in the article: both the good (getting an app up and running quickly), and the more painful to read ("Flutter's ability to execute leads a lot to be desired, particularly on iOS"). While Google is the primary sponsor for Flutter, it's an open source project, and so as ever having reproducible bug reports and ideally pull requests is how we make it better.
The raison d'être for Flutter is simple: we don't think you should have to write the same code six times for your app to reach each major desktop, mobile and web platform. This abstraction is not free, but we think it's worth the bet, and there are some cool apps being built with Flutter, plenty of which have been awarded accolades like Apple Editor's Choice. We're not the solution for every app out there, but there are startups who don't have the developer team size to build multiple apps but can benefit from Flutter, as well as larger companies for whom Flutter lets them unify their app development team behind a single codebase.
A few quick comments I wanted to make:
- Yes, we have a large number of open issues -- over 9,000 at the last count, but not all issues are bugs. We're somewhat unique in bringing together tools, packages, framework and engine issues into a single database, also merging feature requests, bugs and even API doc requests together. Our general philosophy is that it's better to have it out in the open rather than (for example) to prematurely close issues that we don't plan to work on ourselves. We're also not unique as a large open source project in having lots of open issues (also see projects like PyTorch, Rust and VSCode). Lastly, it's important to count the number of issues _closed_, which is over 50,000, representing bugs fixed, new features implemented, and so on. We document the triage process here: https://github.com/flutter/flutter/wiki/Triage ↗
- I'm surprised that the author considers packages an inevitable weakness. We've deliberately kept the core of Flutter relatively small, because it enables us to iterate on packages at their own pace. We could have taken the approach of building things like XML parsing, HTTP servers, geolocation and so on into the core of Flutter, but it wouldn't automatically make them more robust. With a package model, we can fix a specific issue without requiring a whole release cycle for every part of Flutter. Over the last year since the author wrote this article, our package maturity has greatly improved, and I'd be interested to know whether this is noticeable.
- Lastly, the underlying fear expressed in the article seems to be that Google will at some point just give up with Flutter. I understand this, since we don't have an immaculate reputation in terms of long-term support. I will say that this question doesn't come up internally with our stakeholders, though. There are over 400,000 apps in the Play Store that use Flutter; about 1,000 Google engineers building highly-strategic products using Flutter; and a healthy ads revenue from apps that use Flutter. The project more than pays for itself, and I can't honestly envisage any scenario in the next decade where Google would choose to squander all that.
Keep the feedback coming: we're listening.
I was heavily involved with the rollout and maintenance of React Native(RN) at my previous job. This post touches on an interesting point that has just now crystallised in my head.
In particular the OP writes:
We adopted RN because we had a lot of web developers(hundreds) and wanted to enable them in contributing to our app. We explicitly didn't make it a goal to achieve code sharing, yet we did, to the tune of 90% of the code. Overall RN was successful for us.
However, one thing became apparent immediately: the RN developers needed support from native teams. As soon as the RN developers hit a problem that required bridging native APIs or a bug that required platform knowledge, they end up blocked with no way to unblock themselves. Luckily we could create a team of platform experts dedicated to supporting these developers.
This highlights the unfortunate paradox with cross platform tech. It's a great choice for solo developers or small startups looking to find product market fit and iterate quickly. They might be fooled into thinking that they can get by without learning the platform native methods and languages, only to find that they end up stuck when the leaky abstraction eventually leaks.
On the other hand, a well resourced company that can dedicate a team of platform experts as support for the cross platform developers will not suffer this problem, but is cross platform the right choice for a well resourced company? Such a company has probably already found product market fit and is better of paying the higher cost of native development to build a higher quality app.
A big takeaway from my RN experience is: One might expect that an RN developer can get away with knowing less about mobile than a native developer. Counter-intuitively, the opposite is true. A solo RN developer will, of course, need to know JS and React, but when the abstraction leaks they'll also need to be comfortable with Java, Kotlin, Swift, Objective-C, the respective build systems(CocoaPods & Gradle), and even C++.
If one considers RN's origin, being an internal Facebook framework. It all makes sense. RN was built to allow more developers at Facebook to contribute to their apps, without requiring them to learn native technologies or languages. Of course, Facebook has the best imaginable team to support these developer, the RN team itself.
Disclosure: never done any iOS development, only android as a hobby/personal projects. I'll be first to admit I have always hated Java with a passion. So when Kotlin came along I was thrilled. It still piggybacked on the wretched and slow as hell JVM but at least the syntax was pleasant to work with and didn't offer one way to get from A to B which involved 3 abstract classes, 5 factories and two ultra wide monitors to fit your class names. Flutter came out iirc about a year later and I was on a bus going to a friends's house on the other end of the country. I pulled out my laptop and spent the next 4 hours fiddling with it. And even though it was young and far not mature, I have to admit, I enjoyed it and managed to make a fully functioning app in that time. I had fiddled with dart a bit while I was still in university iirc, just because it was a promising alternative to js(which I also hate with a passion). And even with my rusty memories of it, I felt right at home. It is true, flutter gives you a far greater flexibility when you are building a UI than any of the native solutions. But I feel like the author(s) of the article made one fundamental mistake - depending heavily on components developed by other people. The truth is, flutter is a good choice when you want to do a custom UI at a relatively low price(in terms of how much time and effort you need to spend on it, compared to the native solutions). In addition for cross platform development, dart, unlike javascript, is entirely predictable.
BUT! If you are working on a complex application which requires a lot of resources and clever ways to keep a low footprint, you might be better off with the native solutions(even though dart has a very mature ffi). I guess a similar comparison would be something like tinygo and micro python for embedded development - good enough for simple things, but anything beyond that, sack them and stick to C/C++.
You mention Ionic at the end, so I have to comment as the co-founder :)
The first thought is on maintenance and support from Google/Facebook compared to someone like Ionic. One of the things people don't think about before it's too late is support, and Ionic is unique in mobile in that we actually make money from supporting our technology directly for customers. We have direct support available for our auth/security/data storage plugins, cloud services, and open source projects. We literally will respond to customer support tickets and make fixes/patches on a weekend if we have to.
Is there any other company out there doing what Ionic is in mobile? You mention having issues with the Web View component, is Google or Facebook ever going to prioritize your issues? It's not likely, they don't have that kind of business model around their technology like Ionic does. Facebook builds RN for itself, and who knows what Google's end-goal is with Flutter (drive GCP adoption? push its ad network?) but it's certainly not to monetize it through dedicated support for the most significant users of it. I'm proud that the Ionic stack is the most user-aligned offering out there because we're literally in the business of supporting and extending users of our OSS stack.
On the Web View side, we've recently shipped one of the first mobile micro-frontend projects in the ecosystem called Ionic Portals which is basically an awesome Web View component powered by our tech and expertise building web view experiences on mobile. Right now it doesn't have RN or Flutter bindings but we are working on them this year. This has been a pretty interesting shift for us and we're now working with traditional native teams not using the traditional Ionic stack:
https://ionic.io/portals ↗
In the article, he mentions the need for a DOM parser dependency for his app, as Swift “does not have one.”
I have used Foundation XML parsers[0] for many years, but they are general-purpose; not specifically modeled on DOM or HTML, which probably limits usefulness on some Web content.
That said, if he has control of the content (don’t know the app, so I am not sure), then there should be no reason that they couldn’t render it in XHTML, so the Foundation parser could be used reliably. In the article, he mentions that the content is XHTML. I have to assume that AEXML[1] is easier to use than the built-in parser. It uses Foundation parsing (it actually seems to be a lightweight wrapper for the built-in parser), under the hood (and seems to be a very well-written dependency).
So, it could be posited that he would only need one dependency for his native version, if he wanted to handle the XHTML parsing, himself.
Personally, I am a huge believer in native platform development, having many, many scars from the compromises required for cross-platform solutions.
That said, I totally understand why folks prefer cross-platform development, and can’t, in good conscience, recommend a native approach for all apps.
[0] https://developer.apple.com/documentation/foundation/archives_and_serialization/xml_processing_and_modeling ↗
[1] https://github.com/tadija/AEXML ↗