All posts
8 min read·Jul 2026

How to hire a Flutter developer who ships production apps

Hiring a Flutter developer is easy until the app hits real devices, real data, and the App Store review queue. Here's how to tell a shipper from a demo-builder before you sign.

Every Flutter portfolio looks the same: a counter, a to-do list with a Hero animation, a weather screen hitting one REST endpoint. It all runs at a buttery 60fps in the iOS simulator on an M-series Mac. And none of it predicts what happens when the same code meets a Redmi Note 10 with 4GB of RAM, a scrolling list backed by 40,000 SQLite rows, and a subway tunnel that drops the connection mid-request. That is the exact gap where Flutter hires go sideways.

We've inherited enough abandoned Flutter codebases to recite the pattern from memory. The demo demos, the founder signs, and then scroll janks below 30fps, the release build crashes on a null the debug build tolerated, and the APK ships at 90MB because someone bundled uncompressed PNGs and every locale of the intl package. Flutter is a genuinely good framework — we ship it for clients who want one codebase across iOS and Android — but the thing you're hiring for isn't 'writes Dart.' It's 'has lost a weekend to `flutter build apk --release` and knows why.' Here's how to find that person.

The demo-to-production gap is where they'll fail

A debug build and a release build are two different programs. Release flips on AOT compilation, tree-shaking, and R8/ProGuard on Android — and that's precisely where it breaks. A developer who only ever ran `flutter run` hands you code that dies on `flutter build apk --release`, usually because R8 stripped a class the JSON parser looked up by reflection, or minification renamed a native method a plugin called over a channel. Ask directly: what's the last bug you only saw in release, and how did you trace it? If they've never watched `--release` misbehave where debug was fine, they haven't shipped.

The second tell is device reality. The simulator has no GPU throttle, no memory ceiling, and a LAN-speed network — it is lying to you. A shipper profiles on physical low-end hardware, talks in frame budget (16.6ms at 60Hz, 8.3ms at 120Hz), and knows a ListView.builder still stutters if each row rebuilds an unmemoized subtree or decodes a full-res image on the raster thread. 'Add const' is a warm-up answer. Push them: I want to hear DevTools timeline, the raster-vs-UI thread split, RepaintBoundary, and 'find the widget rebuilding when nothing it depends on changed.'

State management is a decision, not a religion

Every Flutter developer has a take on Riverpod vs. Bloc vs. Provider vs. GetX, and most will sell you their pick as objective truth. The honest answer is that it depends on the app. The wrong answer is GetX for anything you plan to maintain — its global service locator hides dependencies until testing becomes guesswork and a rogue `Get.find` fails at runtime instead of compile time. What you want is a reason tied to your project: Bloc when logic is complex and you need every transition traceable and unit-tested; Riverpod when you want compile-time provider safety and less boilerplate. A senior asks about your team's size and Flutter experience before recommending anything, because the target is code the next hire can read.

The red flags sit at both extremes: clean architecture with three abstraction layers on a five-screen app, or no architecture at all with API calls fired from `initState` and everything mutated through setState. The first bills you for ceremony; the second is fine at launch and unmaintainable by feature three, when two screens fight over the same state and neither owns it. The person you want has shipped enough to value consistency over cleverness and can defend their choice in one plain sentence.

The native seam is where offshore hires often thin out

Flutter is one codebase right up until it isn't. Background location, exact-alarm push behavior, biometric auth, StoreKit and Play Billing, a BLE peripheral — each drags you into platform channels and real Swift and Kotlin. This is where a lot of 'Flutter developers' go quiet: they can add a pub.dev package but can't debug it when the Android side throws a PlatformException the plugin author never mapped, or when an AGP bump breaks the build. Ask what native code they've written or patched. 'I forked a plugin to handle the Android 14 foreground-service-type requirement' is the answer; 'I only use packages' means a wall on the first feature the ecosystem doesn't cover cleanly.

This matters most when hiring offshore or a dedicated remote developer, which is entirely reasonable — a lot of excellent Flutter talent is in India, Pakistan, and beyond, and we run distributed teams daily. The bar doesn't move by geography: can they own the native seam or do they hand it back to you? Someone fluent in Gradle, provisioning profiles, code signing, and the review process saves you weeks. Someone who's never submitted an app learns on your clock — and App Review runs a 24-to-48-hour loop per rejection, so a Guideline 4.3 or 5.1.1 bounce three times over is two lost weeks, not two lost days.

What to actually put in the technical screen

Skip the algorithm puzzles; inverting a binary tree tells you nothing about Flutter. Give one small real task: fetch a paginated list from an API, cache it locally, survive going offline mid-scroll, and don't drop frames scrolling 500 items. That single exercise exposes everything — async and cancellation, error states, list virtualization, whether they reach for Hive or sqflite or shove JSON in SharedPreferences, and whether they build the empty and error UI or only the happy path. A shipper's version handles the spinner, the retry, and 'no results' unprompted, because that plumbing is 40% of a real app.

Then ask about the parts nobody demos. How do they split build flavors for staging and production? Where do secrets live so the API key isn't sitting in Git history? How does CI produce a signed artifact without a human at a keyboard? How do they stage a rollout and watch crashes after release? Someone who says flavors, `--dart-define`, a Codemagic or Fastlane pipeline, and Crashlytics or Sentry with a mapping-file upload has shipped apps real people use. Someone who's never thought past `flutter build` has shipped a portfolio piece. Checking costs you one conversation; skipping it costs you the rebuild.

Keep reading
All posts

If you'd rather hand the whole thing to a team that's already fought the release pipeline, talk to us about your Flutter build.