Member-only story

5 More Flutter Libraries I Regret Using in Production (Part 2)

I ripped out GoRouter and Secure Storage after they caused data loss and breaking changes. Here are the stable alternatives.

4 min read21 hours ago
Press enter or click to view image in full size

My last post about removing GetX and Connectivity Plus struck a nerve. It turns out I wasn’t the only one suffering from “Resume-Driven Development.”

But we didn’t stop there. As our app scaled to 50k+ daily users, we found 5 more “standard” libraries that couldn’t handle the pressure of a real production environment. These aren’t necessarily “bad” code — but they prioritize Setup Speed over Production Stability.

Here is what I removed, the specific bugs that forced my hand (with receipts from the community), and the boring tools I replaced them with.

1. Flutter Secure Storage (For Tokens)

The Promise: “Safe, encrypted storage for sensitive data.” The Reality: Random data wipes on iOS.

We used this to store Auth Tokens (JWTs). Then came the support tickets: “I updated the app and I got logged out.”

I thought it was my code until I checked Reddit. There are entire threads in r/flutterhelp detailing how an iOS update or even a simple reinstall can wipe the Keychain if kSecAttrAccessible isn't configured perfectly.

  • The Issue: On iOS, the data persists across reinstalls by default (which is a security risk for some), but randomly vanishes during OS updates.
  • The Jank: On Android, older versions of the library performed encryption on the Main Thread, causing visible UI stutter during app launch.

The Fix: Drift (SQLCipher). Since we already moved to Drift for our relational data (as mentioned in Part 1), we simply enabled the SQLCipher extension. This gives us a fully encrypted, synchronous database that doesn’t rely on the flaky OS Keychain for critical persistence. It never “forgets” data unless we tell it to.

2. Webview Flutter (The Official Package)

The Promise: “Display web content in your app.” The Reality: The keyboard nightmare.

The official WebView plugin feels like an MVP. The biggest dealbreaker? Input fields.

If you search StackOverflow for “webview_flutter file upload android”, you will find hundreds of developers screaming into the void. The official plugin struggles to open the native File Picker (<input type="file">) on many Android devices. Worse, on Android 10/11, the virtual keyboard often covers the input field inside the WebView, making it impossible for users to type.

The Fix: flutter_inappwebview. It is a beast. It handles file uploads, complex JS injection, custom context menus, and window popups correctly. It is what you use when you need a real browser, not just a viewing window.

3. Permission Handler (For “Control”)

The Promise: “The standard way to request permissions.” The Reality: It forces you to write OS-specific spaghetti code.

I used to love this package. But with Android 14 and iOS 17, permissions have become a nightmare of “Granular Access.”

  • The Trap: permission_handler gives you raw access, but it doesn't abstract the complexity. You have to manually handle:
  • Android 13: Requesting photos vs videos vs audio separately.
  • iOS 14+: The “Limited Photo Library” access logic.
  • The Bug: There is a long-standing issue on GitHub where openAppSettings() returns true but fails to open the settings page on certain Android ROMs (Xiaomi/Vivo), leaving users stuck in a loop.

The Fix: Specialized Wrappers. Instead of handling raw permissions, use packages that handle the feature logic for you.

  • For Media: Use wechat_assets_picker (Handles "Limited Access" UI automatically).
  • For Files: Use file_picker (Handles the Scoped Storage logic).
  • Rule: Stop managing raw permission states; let the feature-specific package handle it.

4. Flutter SVG (For Icons)

The Promise: “Render SVG files like native vectors.” The Reality: The scroll performance killer.

We used SVGs for everything. Our lists looked crisp. But our scroll performance on mid-range Android phones was garbage.

The Reason: Parsing XML and rendering Paths is heavy. flutter_svg does this parsing on the Main Thread. A user on Reddit (r/FlutterDev) recently proved that simply applying a ColorFilter to an SVG in a ListView caused a 50% FPS drop compared to a standard Icon.

The Fix: Icon Fonts (icomoon). We converted our SVGs to a Custom Font. Flutter renders text (fonts) incredibly fast because it uses the GPU’s text engine.

Result: We swapped 50 SVGs for 50 Icon glyphs, and the scroll jank vanished instantly.

5. Intl (The Official Localization)

The Promise: “The standard way to translate apps.” The Reality: Boilerplate hell and ARB files.

Why do I need to edit a specialized .arb file, then run a generator, then import a generated class just to change "Hello" to "Hola"? The Intl workflow is archaic. It makes adding a simple string feel like a chore, so developers stop adding strings.

The Fix: Slang (fast_i18n). You write standard JSON/YAML files. It generates the Dart code instantly (no build_runner needed). It’s type-safe, supports pluralization, and is 10x faster to set up.

Summary

The best library is the one you don’t have to think about.

If a tool requires you to constantly check StackOverflow for “keyboard covering input” workarounds (webview_flutter) or debug mysterious data wipes (secure_storage), it's not a tool—it's a liability.

Missed Part 1? I broke down why I removed GetX, Hive, and Connectivity Plus in the first article here: https://medium.com/dev-genius/the-5-flutter-libraries-i-regret-choosing-for-production-and-what-i-use-instead-35251865e773

Question for the comments: Are you still using .arb files for translations, or have you moved to JSON? Let me know below. 👇

Simra Husain

Written by Simra Husain

Writing deep dives on jank, rendering, GC, and real-world debugging. Follow on LinkedIn for quick updates, and Subscribe here for new posts.

Comments