{"id":201,"date":"2026-10-07T06:40:00","date_gmt":"2026-10-07T05:40:00","guid":{"rendered":"https:\/\/arrowlancer.ma\/blog\/?p=201"},"modified":"2026-10-07T06:40:00","modified_gmt":"2026-10-07T05:40:00","slug":"flutter-maintenance-morocco-tma-provider-2026","status":"publish","type":"post","link":"https:\/\/arrowlancer.ma\/blog\/en\/flutter-maintenance-morocco-tma-provider-2026\/","title":{"rendered":"Flutter maintenance Morocco 2026: picking a TMA provider"},"content":{"rendered":"<p>A Flutter app delivered eighteen months ago has already lived through roughly six stable SDK releases. Flutter ships a stable version about once a quarter, Dart moves with it, and every one of those steps shifts something: a deprecated API that finally gets removed, a rendering behaviour that changes, a version constraint that blocks a package. In the same period, Google Play and the App Store each raised their build requirements at least once.<\/p>\n<p>That is why so many Moroccan SMEs end up with an app that still runs fine on users\u2019 phones but no longer compiles on the next provider\u2019s machine. The code did not move. Everything around it did.<\/p>\n<p>If your app was built by a freelancer or a small shop you can no longer reach, the real question is not whether to rebuild from scratch. A two or three year old Flutter codebase can almost always be taken over. You just need a provider who knows where to start.<\/p>\n<h2>What breaks in a Flutter app isn\u2019t what breaks in a native one<\/h2>\n<p>In a native app the instability surface is fairly readable: the language (Swift or Kotlin), the platform SDK, a handful of libraries. When Apple changes an API, you read it in the Xcode release notes and you fix it.<\/p>\n<p>Flutter adds two layers on top. The Flutter SDK and the Dart language move on their own calendar, independent of Apple and Google. And nearly every feature that touches the phone (camera, notifications, biometrics, payment, location, secure storage) goes through a community package on pub.dev that itself wraps native code. So you inherit Apple\u2019s calendar, Google\u2019s calendar, Flutter\u2019s calendar and the calendars of several dozen volunteer maintainers. None of that is an argument against Flutter, which is often still the right call for a company that wants two platforms with one team, as we set out in our <a href=\"https:\/\/arrowlancer.ma\/blog\/en\/native-vs-flutter-morocco-mobile-app-2026\/\">native vs Flutter decision guide<\/a>. It just means maintenance needs one extra skill: knowing which floor of that stack the failure sits on.<\/p>\n<h2>Every stable SDK release moves something<\/h2>\n<p>On paper, a Flutter SDK upgrade is painless. In practice deprecations have a shelf life: an API marked obsolete is eventually deleted, and if you skipped four releases you get the deletion without ever having seen the warning.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/storage.googleapis.com\/arrowlancer-prod.firebasestorage.app\/blog-ma\/tma-flutter-maroc-prestataire-2026\/1.jpg\" alt=\"Flutter maintenance Morocco 2026: picking a TMA provider\" loading=\"lazy\" \/><\/p>\n<p>A few well-documented breaks, to give a sense of the work involved:<\/p>\n<ul>\n<li>Material 3 becoming the default theme: every component\u2019s appearance changes without a single line of your code moving.<\/li>\n<li>WillPopScope replaced by PopScope for back-navigation handling, with different behaviour on forms that ask for confirmation.<\/li>\n<li>The Android Gradle plugin declaration moving to the declarative style, which invalidates build files generated by older Flutter versions.<\/li>\n<li>Dart version constraints in pubspec, which stop the build dead as soon as the installed SDK falls outside the declared range.<\/li>\n<\/ul>\n<p>The practical consequence is that you do not jump from Flutter 3.3 to the latest release with one command. A provider who knows the job moves in steps, climbs version by version, and checks the build plus the critical screens at each stop. They also pin the project\u2019s Flutter version, with fvm or an equivalent, so two developers aren\u2019t compiling against two different SDKs. If nobody raises any of this during the sales conversation, note it.<\/p>\n<h2>pub.dev: the dependency nobody is watching<\/h2>\n<p>Open your app\u2019s pubspec.yaml. You will probably find between twenty and fifty direct dependencies, and several times that in transitive ones. Each is maintained by someone who does not know you and owes you nothing.<\/p>\n<p>The flutter pub outdated command gives you the real picture in a minute: what is one minor version behind, what is a major version behind, and what no longer resolves at all. On pub.dev every package shows its last publish date and, where it applies, a \u201cdiscontinued\u201d banner. That is where the bad news almost always lives.<\/p>\n<p>The riskiest packages are the ones wrapping a native SDK: webview, local notifications, permission handling, QR scanners, and above all payment gateways. An abandoned wrapper around a payment SDK that keeps evolving on its own is a dead end with a date on it. You will either swap the package or write the native bridge yourself, and both have a price. Another useful tell is a dependency_overrides block. Sometimes it is legitimate and temporary, but often it is the fingerprint of a version conflict that was worked around rather than resolved, and it comes back on the next SDK upgrade.<\/p>\n<h2>What comes back up from the iOS and Android layers<\/h2>\n<p>Flutter does not exempt you from either store\u2019s rules. Google Play sets a minimum target API level every year for publishing updates, and Apple periodically requires binaries to be built against a recent iOS SDK. The exact dates and levels change, so check them in the Play Console and in Apple Developer announcements rather than trusting a number you read in an article. In concrete terms those requirements mean:<\/p>\n<ul>\n<li>bumping Android Gradle Plugin and Kotlin, sometimes the JDK the project builds with;<\/li>\n<li>updating Xcode, which sometimes forces a macOS upgrade, which sometimes forces a newer Mac;<\/li>\n<li>regenerating iOS pods and rereading the permissions declared in Info.plist, which Apple reviews on every submission;<\/li>\n<li>tracking Android behaviour changes (edge-to-edge display, memory limits) that degrade the real UI without producing a single compile error.<\/li>\n<\/ul>\n<p>Then there is the admin side, which blocks more handovers than the code does. The Apple Developer account (99 USD a year) and the Google Play account (25 USD once) must be in your company\u2019s name, not the departed developer\u2019s. The Android signing keystore cannot be regenerated: if the app is enrolled in Play App Signing you can request an upload key reset, otherwise you lose the ability to update the existing listing. We covered these points in our guide to <a href=\"https:\/\/arrowlancer.ma\/blog\/en\/publish-mobile-app-morocco-app-store-play-store\/\">publishing a mobile app in Morocco<\/a>.<\/p>\n<h2>Flutter maintenance Morocco: 2026 price ranges<\/h2>\n<p>What you pay depends less on the number of screens than on the accumulated debt and the level of commitment you ask for. The ranges below reflect what the Moroccan market charges in 2026, excluding new features billed as projects.<\/p>\n<ul>\n<li><strong>Monitoring and fixes<\/strong> (crash watch, SDK upgrades, store compliance, no new features): 2,500 to 6,000 MAD per month for a simple app.<\/li>\n<li><strong>Standard maintenance with an SLA<\/strong> (contractual response time, fixes, small changes, one or two releases per quarter): 6,000 to 15,000 MAD per month.<\/li>\n<li><strong>Business-critical app<\/strong> (online payment, custom backend, several apps, on-call): 15,000 to 35,000 MAD per month, sometimes more.<\/li>\n<li><strong>Initial handover audit<\/strong>: 8,000 to 25,000 MAD depending on codebase size and documentation.<\/li>\n<li><strong>SDK catch-up<\/strong> covering two or three years of drift, billed once: 20,000 to 60,000 MAD.<\/li>\n<\/ul>\n<p>Day rates spread widely, from an experienced Flutter freelancer to a structured agency, and the gap mostly buys continuity for the week the person who knows your code is off sick. For the wider budget framing, the line items in <a href=\"https:\/\/arrowlancer.ma\/blog\/en\/mobile-app-maintenance-cost-morocco-2026\/\">mobile app maintenance costs in Morocco<\/a> are the same whether the app is Flutter or not.<\/p>\n<h2>Mobile generalist or Flutter specialist: what to check before signing<\/h2>\n<p>Five questions usually tell you who you are talking to.<\/p>\n<ol>\n<li><strong>Which Flutter version runs in your CI?<\/strong> A specific number, a pinned version file, a pipeline: anything beats \u201cthe latest one\u201d.<\/li>\n<li><strong>Show me a major migration you ran.<\/strong> Not an app built from scratch: an app taken over and brought forward several major versions, with how long it took.<\/li>\n<li><strong>Who on your team reads Kotlin and Swift?<\/strong> A Flutter team that cannot go down into the android\/ and ios\/ folders will not fix half of the real failures.<\/li>\n<li><strong>How do you handle an abandoned package?<\/strong> A good answer talks about a maintained fork, an evaluated replacement, or a hand-written native bridge.<\/li>\n<li><strong>What happens if we leave?<\/strong> Git repository on your side, store accounts in your name, build documentation kept current. Those clauses are listed in our guide to <a href=\"https:\/\/arrowlancer.ma\/blog\/en\/switch-it-provider-morocco-2026\/\">switching IT provider in Morocco<\/a>.<\/li>\n<\/ol>\n<p>A serious mobile generalist can do this work perfectly well. What disqualifies a provider is not the absence of a Flutter label, it is proposing a rebuild before opening the code. A full rewrite costs several times a catch-up, and you pay again for features you already own.<\/p>\n<h2>The handover audit, before the first line of code<\/h2>\n<p>Nobody should commit to maintaining an app they have not built themselves at least once. The handover audit usually takes three to ten working days, and the sequence is fairly stable.<\/p>\n<ol>\n<li>Clone the repository on a clean machine and attempt an Android build, then an iOS build, with no outside help. How long that takes is the first measurement of the project\u2019s health.<\/li>\n<li>Record the versions (Flutter, Dart, AGP, Kotlin, JDK, iOS deployment target) and the distance from what is supported today.<\/li>\n<li>Run flutter pub outdated and flutter analyze, then sort every dependency into current, behind, or unmaintained.<\/li>\n<li>Inspect android\/ and ios\/ to spot what was hand-edited away from the generated templates.<\/li>\n<li>Look for secrets committed in plain text, and check the Firebase config files, certificates and keystore.<\/li>\n<li>Rebuild the release chain and confirm who actually holds access to the store accounts, the backend and the DNS.<\/li>\n<li>Deliver a ranked risk list with a costed 90-day plan, and what can safely wait.<\/li>\n<\/ol>\n<p>That deliverable keeps its value even if you hand the maintenance to someone else afterwards. Mostly it avoids the common scenario: maintenance starts, the first store update is rejected, and nobody budgeted the three weeks of catch-up it takes.<\/p>\n<h2>CNDP: what has to follow when maintenance changes hands<\/h2>\n<p>An app that collects a name, a phone number, a location or a purchase history processes personal data under Law 09-08. Changing provider does not change who is the data controller: you are. At the switchover, your CNDP declaration has to reflect reality, including the identity of the technical subcontractor accessing the data. Forms and procedures change, so check the current state on the CNDP website rather than copying a 2022 template. The maintenance contract should frame that access: purpose, duration, a ban on copying the production database into an unprotected test environment, and a notification duty if something goes wrong.<\/p>\n<p>Then comes the cleanup on the old provider\u2019s access: Firebase console, API keys, backend accounts, store test users. As long as those exist, the exposure is yours. Same logic for the third-party SDKs embedded in the app (analytics, crash reporting, push notifications): they send data outside Morocco and belong in your privacy policy and your store listing.<\/p>\n<h2>Frequently asked questions<\/h2>\n<h3>Does a three-year-old Flutter app need rebuilding?<\/h3>\n<p>Rarely. A cleanly written codebase can be brought current in two to six weeks depending on size. A rewrite becomes defensible when the architecture blocks all change (business logic inside widgets, no tests, uncontrolled state management) or when the functional need itself has moved on.<\/p>\n<h3>How long does it take to take over a Flutter codebase with no documentation?<\/h3>\n<p>Budget the audit, then a familiarisation period where the team fixes real defects instead of reading code. On a mid-size app, a provider is usually self-sufficient after four to six weeks.<\/p>\n<h3>The original developer vanished with the Android keystore. What now?<\/h3>\n<p>If the app is enrolled in Play App Signing, you can request an upload key reset from the Play Console and keep shipping updates. If not, you have to republish under a new application ID, which means losing installs, reviews and your rating. Check this before anything else.<\/p>\n<h3>How often should the Flutter version be upgraded?<\/h3>\n<p>Once or twice a year suits most SME apps, on top of security patches. The goal is not to sit on the latest release, it is to never be more than two major versions behind.<\/p>\n<h3>Is a monthly retainer necessary, or can we pay per incident?<\/h3>\n<p>Pay-per-incident works right up until something is urgent. The day a release gets rejected, the provider\u2019s existing queue comes before you. Even a small retainer mainly buys a response time.<\/p>\n<p>At Arrowlancer in Casablanca, our mobile team takes over existing Flutter and React Native apps: handover audit first, then maintenance with planned SDK upgrades, package tracking and releases on both stores. The detail sits on our <a href=\"https:\/\/arrowlancer.ma\/en\/#services\">services<\/a> page. If your app currently has no maintainer, send us the repository access and the store listing name through the <a href=\"https:\/\/arrowlancer.ma\/en\/#contact\">contact form<\/a> and we will tell you what can be repaired and what has to be replaced.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Flutter SDK upgrades and pub.dev package drift break mobile apps in specific ways. Here are 2026 TMA prices in Morocco and the handover audit to ask for.<\/p>\n","protected":false},"author":0,"featured_media":202,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[119],"tags":[780,219,783,786,789],"class_list":["post-201","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cost_and_planning-en","tag-app-handover-en","tag-flutter-en","tag-flutter-maintenance-en","tag-mobile-app-maintenance-en","tag-morocco-it-budget-en"],"_links":{"self":[{"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/posts\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":1,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/posts\/201\/revisions"}],"predecessor-version":[{"id":204,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/posts\/201\/revisions\/204"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/media\/202"}],"wp:attachment":[{"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/media?parent=201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/categories?post=201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arrowlancer.ma\/blog\/wp-json\/wp\/v2\/tags?post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}