---
title: "Controlling Rollouts in Production: Feature Flags Done Right in Flutter"
description: Master feature flagging in Flutter to dynamically control app features, streamline subscription management, and improve user experience in your fitness app.
image: https://optiblack.com/hubfs/Optiblack%20Vishal%20Rewari%20Product%20Analytics%20(7).png
---

OPTIBLACK

- [Services](https://optiblack.com/services)
- [Customers](https://optiblack.com/customers)

[Book a strategy call](https://optiblack.com/book-a-call)

- [Services](https://optiblack.com/services)
- [Customers](https://optiblack.com/customers)

[Book a strategy call](https://optiblack.com/book-a-call)

[Information](https://optiblack.com/insights/tag/information) Jun 21, 2025, 11:37:43 AM · 8 min read

# Controlling Rollouts in Production: Feature Flags Done Right in Flutter

![Vinay Vashist](https://optiblack.com/hubfs/Untitled%20design-2.png)

Vinay Vashist

Optiblack

![controlling rollouts in production using feature flags](https://optiblack.com/hubfs/Optiblack%20Vishal%20Rewari%20Product%20Analytics%20(7).png)

**Controlling Rollouts in Production: Feature Flags Done Right in Flutter**

# **Introduction**

In today’s fast-moving mobile app ecosystem, delivering personalized and controlled user experiences is more critical than ever—especially in fitness applications, where user engagement, monetization, and retention hinge on offering just the right set of features at the right time.

While building our cross-platform fitness app with Flutter, we faced a common but challenging requirement: supporting six different subscription plans—**Standard** and **Premium**, each with **Weekly**, **Monthly**, and **Annual** durations. Each plan unlocks a unique combination of features, timelines, and access levels. Managing these variations with hardcoded logic or repetitive conditionals would not only bloat the codebase but also introduce risks during feature rollouts and updates.

To solve this, we implemented a robust **Feature Flagging** system—a dynamic, scalable, and modular solution for **Advanced Feature Management**. With this architecture, features can be toggled, tested, or tiered without needing to ship a new version of the app. This enabled us to:

- Seamlessly gate premium or experimental features,
- Dynamically control plan-specific access,
- Implement A/B testing and beta rollouts,
- Maintain a clean, extensible codebase.

In this article, we'll explore how we designed and implemented this system, the Flutter classes that power it, and how it transformed our ability to ship and manage features confidently in production.

Want to watch instead? Watch this 30 mins + tutorial on getting yourself ready with feature flags in Flutter

<iframe style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; border: none;" width="800" height="450" src="https://www.tella.tv/video/cmcdbvv2k000v0bl4ayohbsms/embed?b=1&amp;title=1&amp;a=1&amp;loop=0&amp;t=0&amp;muted=0&amp;wt=1" allowfullscreen allowtransparency=""></iframe>

 

# **The Problem: When simple categorization fails**

As our fitness app evolved, we quickly realized that managing user access through just two broad categories—**Standard** and **Premium**—wasn’t going to scale. While it seemed straightforward on the surface, the underlying complexity was significant. Here’s why:

1. **Feature & Timeline Fragmentation** Each of the six plans (Standard: Weekly, Monthly, Annually and Premium: Weekly, Monthly, Annually) had **distinct feature sets and durations**. Attempting to manage these variations using just a boolean flag like isPremium led to convoluted conditional logic, which became hard to maintain and error-prone. What we needed was a way to **decouple features from rigid plan categories**.
2. **Initial Plan Detection** Determining a user's current plan when they entered the app wasn't always reliable—especially after reinstalls or device changes. This made it difficult to ensure the right set of features were active from the moment the user launched the app.
3. **Real-time Plan Retrieval on App Launch** With dynamic plans and the potential for server-side updates, retrieving the most up-to-date plan details at each app launch became crucial. But fetching and interpreting this data correctly without delaying the UX was a challenge.
4. **Plan Upgrade/Downgrade Management** Supporting seamless **transitions between plans**—whether users upgraded from Standard Monthly to Premium Weekly or downgraded from Premium Annual to Standard Monthly—required a **flexible, centralized logic** to enable and disable the correct features in real-time, without forcing app restarts or deep user interaction.

These limitations signaled the need for a **smarter feature management system**, one that treated features as **independent capabilities** rather than static properties of a plan. That’s when we decided to implement a custom Feature Flagging system tailored to our app's unique requirements.

 

 

# **The Solution: A Scalable Feature Flagging System**

To address the growing complexity of subscription-based feature management, we designed a **Feature Flagging System** tailored for scale, clarity, and flexibility. Here’s how it works:

### **1. Centralized Plan Identification via Enum**

We began by formalizing all possible subscription types using an enum called SubscriptionPlans. This allowed us to treat each plan (Standard Weekly, Premium Monthly, etc.) as a distinct entity, making the logic around access control **explicit and type-safe**:

| enum SubscriptionPlans {   freeTrial,   standardWeekly,   premiumWeekly,   standardMonthly,   premiumMonthly,   standardAnnually,   premiumAnnually } |
| --- |

We also implemented a utility function getSubscriptionPlan() to derive the appropriate enum based on backend values like plan name and duration. This minimized the chances of misclassification and centralized plan parsing logic.

 

### **2. Feature Constants as Identifiers**

All current and upcoming features were declared as **string constants** in a dedicated Features class. This approach provided:

- A single source of truth for all features,
- Support for partial or experimental rollout,
- Easy mapping between feature flags and UI/logic.

| class Features {   static const String realTimeFormCorrection = 'real\_time\_form\_correction';   static const String gamifiedHabitCoach = 'gamified\_habit\_formation\_coach';   ... } |
| --- |

 

### **3. Access Control via Feature Mapping**

We created a featuresAccessMap to define which features were available to each plan. This configuration is **declarative**, making it easy to audit, test, and expand as new plans or features roll out.

| final Map\<SubscriptionPlans, Set\<String\>\> featuresAccessMap = {   SubscriptionPlans.premiumAnnually: {     Features.realTimeFormCorrection,     Features.advancedCoachingAI,     ...   },   ... }; |
| --- |

 

This effectively decoupled **plan logic from app logic**—making the feature access system **data-driven** instead of hardcoded.

### **4. A Singleton FeatureManager**

At the heart of this system is the FeatureManager singleton. It is initialized once with the current user’s plan and provides a simple hasFeature() method for any feature check throughout the app.

| FeatureManager.initialize(userPlan); if (FeatureManager.instance.hasFeature(Features.realTimeFormCorrection)) {   // Show this section in the UI } |
| --- |

 

This pattern ensured:

- Global availability of feature logic,
- Consistent feature access checks across the entire app,
- Seamless upgrades or downgrades without needing app restarts or deep context rewiring.

Together, these components formed a powerful, testable, and scalable solution to the problem of managing subscription-based features in a growing app ecosystem.

 

# **Real-World Usage: How Feature Flagging Transformed User Experience**

Implementing a robust feature flagging system wasn’t just a backend or architectural decision — it directly enhanced the **user experience**, **performance**, and **flexibility** of our fitness application. Here’s how it translated into practical, real-world impact:

---

### **1. Seamless Free Trial Experience**

New users get immediate access to the **Free Trial** plan, which unlocks nearly every premium feature for 7 days. This onboarding flow is powered entirely by the feature flagging system:

- No special-case UI code or hardcoding.
- Features are gated via FeatureManager.hasFeature(), making the experience consistent across the app.
- When the trial expires, switching to a limited plan is seamless — feature access just updates automatically based on plan.

### **2. Dynamic UI Based on User Plan**

With a single source of truth (FeatureManager), the app can instantly determine what to show or hide:

| if (FeatureManager.instance.hasFeature(Features.advancedNutritionAI)) {   // Render the advanced nutrition section } |
| --- |

 

This dynamic control:

- Prevents UI clutter for non-eligible users,
- Encourages plan upgrades by graying out premium sections,
- Keeps the UX personalized and relevant.

---

### **3. Support for Upgrades and Downgrades**

When users upgrade or downgrade their subscription (e.g., from Standard Monthly to Premium Annual), the app doesn’t need a restart or reinitialization of all layers:

- The new plan is passed to FeatureManager.initialize(),
- The new feature set becomes available instantly,
- All views react accordingly since they're built around hasFeature() logic.

This allows for:

- In-app plan switching,
- Instant gratification after upgrades (crucial for user retention),
- Zero risk of old feature access lingering post-downgrade.

---

### **4. Feature Experiments and Gradual Rollouts**

Some features are still under development or being A/B tested. Our system makes it easy to expose these features to only certain plans (or even specific user cohorts later on):

- Features like advancedCoachingAI, gamifiedHabitCoach, or wearablesIntegration are already defined in the Features class.
- As they’re ready to roll out, we simply update the featuresAccessMap—no need to touch the UI or business logic layers.

This keeps development decoupled and makes gradual releases safer.

---

### **5. Powerful for Marketing and Monetization**

By explicitly tying features to plans in a single map, we also unlocked several strategic advantages:

- The marketing team can now **clearly communicate plan benefits**.
- The sales team can design **targeted upsell prompts** for locked features.
- Referral programs or limited-time unlocks become trivial to implement via temporary plan overrides.

---

This system not only simplified engineering but also created a foundation for **flexible growth**, **faster iteration**, and a **personalized fitness journey** for every user.

# **Key Takeaways: Building Scalable Feature Management in a Subscription-Based App**

Designing a scalable and dynamic feature flagging system was a **game-changer** for our fitness app. Here are the key takeaways from the journey:

---

## **Treat Subscription Plans as First-Class Citizens**

Instead of just "Standard" and "Premium," we acknowledged the nuance across **timeframes** (weekly, monthly, annually) and built a dedicated enum to represent each unique plan. This clarity helped eliminate ambiguity across both logic and UI.

---

## **One Centralized Source of Truth**

By maintaining a **central map (featuresAccessMap)** linking plans to features, and routing all access checks through FeatureManager.hasFeature(), we ensured:

- No duplicate conditionals or scattered feature checks
- UI, backend sync, and business logic all align automatically

---

## **Support Upgrades, Downgrades, and Expirations Effortlessly**

Thanks to runtime initialization (FeatureManager.initialize()), any change in plan — whether due to payment, trial expiry, or manual switching — reflects across the app instantly and without app restarts.

---

## **Future-Proof Feature Development**

Our modular Features class and mapping approach means we can:

- Add features mid-cycle without touching UI
- Roll out gradually (A/B tests, phased releases)
- Toggle feature access remotely if needed (future cloud integration)

---

## **Business Agility & Monetization**

Product and marketing teams now have a concrete map of what’s tied to which plan. That directly feeds into:

- Feature-based upselling
- Dynamic feature previews
- Promotional campaigns (like unlocking premium features for a week)

---

## **What's Next?**

We’re already thinking ahead:

- **Remote Config Integration** using Firebase or a custom backend to toggle features without releasing updates.
- **User-level feature experimentation** for A/B testing new ideas before full rollout.
- **Analytics-backed decision making**, tracking which features drive the most upgrades.

---

## **Final Thoughts**

Building this system wasn't just about writing cleaner code — it was about **enabling product scalability, personalized UX, and monetization** from the ground up. Whether you're building a fitness app, a productivity tool, or any subscription-based product, investing in smart feature management early pays dividends in the long run.

 

![Vinay Vashist](https://optiblack.com/hubfs/Untitled%20design-2.png)

Vinay Vashist

Tech @ Optiblack

[#Information](https://optiblack.com/insights/tag/information)

/ Keep reading

## More from Optiblack

[![Action Tour Guide Selects Optiblack as Analytics Partner to Build Customer Intelligence for the GuideAlong App](https://optiblack.com/hubfs/Optiblack%20Vishal%20Rewari%20Product%20Analytics%20(25)-2.png) News Action Tour Guide Selects Optiblack as Analytics Partner to Build Customer Intelligence for the GuideAlong App](https://optiblack.com/insights/action-tour-guide-selects-optiblack-as-analytics-partner-to-build-customer-intelligence-for-the-guidealong-app) [![How We Built Optiblack's Dribbble Presence from Existing Product Work](https://optiblack.com/hubfs/image-png-Oct-29-2026-10-09-16-4403-AM.png) Case Studies How We Built Optiblack's Dribbble Presence from Existing Product Work](https://optiblack.com/insights/how-we-built-optiblacks-dribbble-presence-from-existing-product-work) [![From a Sweetener Store to a Metabolic Health Brand: Reeba’s Website Transformation](https://optiblack.com/hubfs/undefined-Oct-24-2026-09-16-01-7132-AM.png) Case Studies From a Sweetener Store to a Metabolic Health Brand: Reeba’s Website Transformation](https://optiblack.com/insights/reeba-shopify-website-transformation)

/ 15-minute exploration call

## Turn these insights into revenue.

We'll go through your CRM, product, and analytics data together and show you exactly where growth is leaking. No setup. No dashboards. Just signal.

[Book a strategy call →](https://optiblack.com/book-a-call)

[OPTIBLACK](https://optiblack.com/)

 US: 1309 Coffeen Ave, Suite 1200, Sheridan, WY 82801 · +1 682 297 2970 — India: 297 Designs, 74 SBK Society, Paldi, Ahmedabad 380007 · +91 9819394297

 Services

[Data services](https://optiblack.com/services) [CRM services](https://optiblack.com/services) [AI services](https://optiblack.com/services) [Book a call](https://optiblack.com/services)

 Company

[Customers](https://optiblack.com/customers) [About Us](https://optiblack.com/about-us) [Insights](https://optiblack.com/insights)

 © 2026 Optiblack · 2× Mixpanel Partner of the Year · vishal@optiblack.com

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Vinay Vashist",
    "url" : "https://optiblack.com/insights/author/vinay-vashist"
  },
  "dateModified" : "2025-06-26T18:10:41.012Z",
  "datePublished" : "2025-06-21T06:07:43.000Z",
  "headline" : "Controlling Rollouts in Production: Feature Flags Done Right in Flutter",
  "image" : [ "https://optiblack.com/hubfs/Optiblack%20Vishal%20Rewari%20Product%20Analytics%20(7).png" ],
  "mainEntityOfPage" : {
    "@id" : "https://optiblack.com/insights/controlling-rollouts-in-production-feature-flags-done-right-in-flutter",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://optiblack.com/hubfs/Group%201234.png"
    },
    "name" : "Optiblack"
  }
}
```