Feature Flags in Flutter: Smarter Releases with ConfigCat
Releasing new features in a mobile app can feel like walking a tightrope, especially when updates require going through lengthy App Store and Google Play review processes, and users still need to download the new build. That's where feature flags come in. They are software development tools that give developers the power to toggle features remotely, test new functionality safely, and control rollouts without shipping a new app version.
This guide shows you how to use feature flags in Flutter (Dart) with ConfigCat, focusing on best practices, manual polling, offline support, and real-world examples.
Why Use Feature Flags in Flutter Apps?
Feature flags (also called feature toggles) are a best practice for Flutter app development. They help you:
- Test in production safely by targeting specific users while others see the existing version.
- Turn off features remotely, without resubmitting your app for review.
- Roll out features gradually to monitor performance and stability.
- Decouple release from deployment, giving your team more control over what users see.
These benefits are especially useful in mobile development, where deployment cycles can be slow and risky.
I'm sure you can agree that these benefits are worthwhile, especially when working with an evolving product.
How ConfigCat Fetches Flags: Polling Modes Explained
In ConfigCat, polling refers to how your app fetches the latest feature flag values from ConfigCat's servers.
There are three main polling modes:
- Auto Polling: Fetches flags periodically in the background.
- Lazy Loading: Fetches only when you ask for a flag, with optional caching.
- Manual Polling: You control exactly when the flags are fetched.
Why Mobile Developers Prefer Manual Polling
Manual polling gives mobile apps full control over when network calls are made. This is important because:
- Mobile apps have startup performance concerns
- You don't always want to fetch data unless necessary (e.g., poor connectivity)
- You want to minimize battery and network usage
Let's now look at an example of how to implement Manual Polling.
Setting up ConfigCat with Manual Polling in Flutter
Here's a realistic example: you're building a weather app, and you've developed a new radar map feature that you want to release only to beta testers. Here's how you can do it:
Step 1: Add Dependencies
The first is the ConfigCat client dependency. I'll use shared_preferences for caching (explained soon).
dependencies:
configcat_client: ^2.1.0
shared_preferences: ^2.2.0
Step 2: Initialize ConfigCat with Manual Polling
import 'package:configcat_client/configcat_client.dart';
final client = ConfigCatClient.get(
sdkKey: 'YOUR-CONFIGCAT-SDK-KEY', //FOUND IN YOUR CONFIGCAT ACCOUNT
options: ConfigCatOptions(
pollMode: PollMode.manualPoll(),
),
);
Step 3: Fetch Flags Using forceRefresh() at App Startup
So far, I've set up manual polling, but I also need to tell ConfigCat to fetch the latest flags when the app launches by calling the forceRefresh() method on the client.
await client.forceRefresh();
Then, use the flag value:
bool isRadarMapEnabled = await client.getValue(
'radar_map_feature_enabled',
false,
);
if (isRadarMapEnabled) {
// Show new feature
} else {
// Fallback UI
}
Making Feature Flags Persistent in Flutter Using SharedPreferences
By default, ConfigCat stores flag values in memory. That means values are lost when the app restarts. This isn't ideal for mobile apps, which are frequently closed and reopened.
Let's fix that with SharedPreferences.
Step 1: Create a Simple Cache Helper
import 'package:shared_preferences/shared_preferences.dart';
class ConfigCatCache {
static const String _cacheKey = 'configcat_cached_flags';
static Future<void> save(String data) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_cacheKey, data);
}
static Future<String?> load() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(_cacheKey);
}
}
Step 2: Save Config After a Refresh
await client.forceRefresh();
final allFlags = await client.getAllValues();
await ConfigCatCache.save(jsonEncode(allFlags));
Step 3: Use Cached Values When Offline
final cachedString = await ConfigCatCache.load();
if (cachedString != null) {
final Map<String, dynamic> flags = jsonDecode(cachedString);
// Use your flags here
}
This allows you to serve the latest cached flag values when the user loses connectivity, making your app's behavior persistent across sessions.
Conclusion
Using feature flags in your Flutter apps may seem like a luxury, but it's actually a best practice. With review times taking longer and users becoming frustrated by frequent updates, it's essential to have control over your application.
To really get the most out of feature flags, you need a solution that’s reliable, flexible, mobile-optimized, and easy to plug into your tech stack. That’s where ConfigCat comes in.
By using ConfigCat feature flags, you get:
- Remote control over what your users see
- Smart rollout strategies
- Detailed user targeting
Whether you're testing in production, experimenting with A/B tests, or gradually rolling out risky features, ConfigCat makes integrating feature flag management into your mobile workflow seamless, giving you the tools to stay agile and safe. Apart from Dart, ConfigCat supports many programming languages, frameworks, and platforms.
Try it out today by signing up for a forever free account, and dive into the official Flutter SDK documentation.
Want to stay updated on the latest feature flag tips, Flutter integration tutorials, and remote config strategies? Connect with ConfigCat on Facebook, LinkedIn, X, and GitHub.
