7 Apps, One Codebase: What an Agency Learns Shipping Flutter for 7 Different Clients
One codebase for iOS and Android is the part everybody sells you. The interesting lessons came from seven products that each stressed a different part of the runtime, from IoT pour tracking to a jewelry catalog that would not stop dropping frames.
Beyond the Marketing Claim: What "Cross-Platform" Really Demands
Every cross-platform framework sells the same line: write once, run everywhere, halve the budget.
The rendering half of that promise is real. Flutter draws its own widgets, so a custom slider looks the same on both platforms without anyone maintaining two of them. The budget half is where it gets complicated, because the expensive parts of mobile work are state management, data modeling, hardware access, and performance profiling, and none of those get cheaper just because there is one codebase.
Over two years we shipped seven Flutter apps:
Fitmate: Hybrid fitness and wellness platform combining real-time calorie tracking, video workout libraries, and interactive coaching dashboards.
Draught Guardian: Commercial beverage supply-chain app featuring real-time IoT sensor telemetry, temperature monitoring, and low-latency Bluetooth/WebSocket streaming.
Gemza: Luxury fine jewelry boutique featuring high-density masonry imagery, custom zoom inspect tools, and frictionless mobile checkout.
Koya: Modern furniture e-commerce app with interactive 360-degree 3D product visualization and custom room dimensioning.
Zyloc: Student transit and school bus tracking app with real-time GPS fleet mapping, live ETA calculations, and emergency push alerts.
Veloq: Racket sports equipment boutique with dynamic technical spec filters and instant inventory checks.
Zivvy: Retail loyalty and digital couponing platform with barcode scanners and push notification feeds.
UI Unified Flutter UI Layer • Custom Design Systems & Widgets • Shared Agency Component Library → SL Reactive Business Logic • BLoC / Riverpod Architecture • Local Hive / SQLite Offline Sync • Secure JWT Key Storage UI → NH Native Hardware Bridges • Low-Latency BLE Streaming • Mapbox & Geolocation Tracking • APNs / FCM Push Channels SL → PL Target Production Stores • Apple iOS App Store • Google Play Store NH → PL
Rendering diagram...
1. What Stays Consistent: UI Rendering & Shared Logic
Flutter's Skia and Impeller renderers are the reason the promise holds up. Older hybrid frameworks translate your UI into native widgets through a bridge and inherit every platform difference along the way. Flutter draws to the canvas itself, targeting the device's refresh rate, typically 60Hz or 120Hz.
What that bought us across all seven apps:
Consistent UI. Custom sliders, branded date pickers, and bottom sheets rendered the same on both platforms. We test on a device matrix plus Firebase Test Lab rather than on every Android handset in existence, and OEM keyboard and text-scaling behavior still produced occasional surprises.
Shared logic. API schemas, form validators, SQLite repositories, and cart calculation were written once in Dart, and their unit tests came along unchanged. The platform channels on either side of them did not.
2. Where the Architecture Differs: Performance by Content Type
The most critical realization from shipping across multiple domains is that different applications stress completely different parts of the mobile runtime.
Case A: Image-Dense Luxury E-Commerce (Gemza & Koya)
Here the bottleneck is memory and image decode, not logic. Fling a masonry feed of 2000px product photos and Flutter will decode every one of them at full size into memory, and the frames start dropping about four rows in.
The fix is unglamorous: decode at display size, cache aggressively, and downsample on the server so the device never receives pixels it cannot show.
Sensor telemetry and live GPS emit hundreds of events per second. Pipe each one straight into the widget tree and you get hundreds of rebuilds per second for a display that refreshes 60 times.
The fix is to move the stream into a background Dart isolate, batch it there, and emit to the UI at 30Hz. Nobody can see the difference, and the main thread stops fighting for its life.
3. What We'd Do Differently (The Honest Lessons)
Three things we would do earlier next time:
Build the shared widget kit on day one. On the early projects, two teams built the same button and three teams built the same bottom sheet. Introducing a common kit around the Zivvy build cut visibly into that duplication.
Pick one state management pattern and stay there. We had Provider in one app, Riverpod in another, and BLoC in a third, and every context switch between them cost a day. We settled on BLoC for the complex apps and Riverpod for the light ones.
Set frame and memory budgets at kickoff, not at QA. A 150MB memory ceiling and a no-dropped-frames budget, checked in sprint review, catches a regression while someone still remembers writing it.
The Economics: Agency Cost Savings vs. Platform Realities
Across the seven projects, one Flutter codebase cost meaningfully less to build, test, and maintain than parallel Swift and Kotlin ones would have. Our internal time tracking puts the saving somewhere between a third and a half per project, and the spread is wide because it depends almost entirely on how much native integration the product needed. Draught Guardian, with its Bluetooth sensor work, saved the least.
Cross-platform is not always the answer:
Project Profile
Flutter Recommendation
Alternative Stack
Consumer apps (e-commerce, social, fitness, SaaS)
Good fit
Flutter or React Native
B2B field apps (fleet tracking, IoT dashboards)
Good fit
Flutter
Deep hardware or OS-specific work (Metal, ARKit)
Wrong tool
Native Swift or Kotlin
Very simple static apps
More than the job needs
Progressive Web App
Frequently Asked Questions (FAQ)
Is Flutter suitable for complex e-commerce apps?
Yes. Gemza, Koya, and Veloq are all catalog apps with faceted filtering and integrated payments. The image handling described above is the part that needs attention; the commerce logic is straightforward.
Does Flutter create larger app binary sizes?
Yes. Flutter ships its own renderer and Dart runtime, so a minimal release build starts around 15MB to 20MB where a native equivalent might be 5MB. Android App Bundles and tree shaking bring the delivered size down. If you are targeting markets where install size genuinely affects conversion, this is a real consideration rather than a rounding error.
How does Flutter handle offline data synchronization?
Pair an embedded database, sqflite for SQLite or Hive and Isar for key-value storage, with a background sync queue. Writes go to the local store first and replay against the server when the connection returns. Conflict resolution is still yours to design, and it is the part that takes the time.
Sharing battle-tested engineering perspectives on Web Development, Mobile Architectures, Enterprise AI, and Cloud Scalability from the NizSol engineering labs.
Was this technical breakdown helpful?
Your feedback directly guides our engineering editorial roadmap.
Partner With NizSol
Ready to scale your next web, mobile, or AI product?
Our team of senior architects and full-stack engineers helps fast-growing companies design, build, and deploy production-grade software with speed and precision.