I got tired of feature flag if statements so I built an ecosystem
**I got tired of writing `if (featureFlags.IsEnabled(...))` everywhere so I built an ecosystem — with A/B testing, user targeting, a self-hosted UI, and a structured migration path from LaunchDarkly**
FtrIO is a C# library that replaces feature flag `if` statements with a `[Toggle]` attribute woven into the compiled IL at build time.
---
**The core idea:**
Instead of this everywhere:
```csharp
if (featureFlags.IsEnabled("SendWelcomeEmail"))
{
SendWelcomeEmail();
}
```
You do this:
```csharp
[Toggle]
public void SendWelcomeEmail() { ... }
SendWelcomeEmail(); // only runs if "SendWelcomeEmail": true in appsettings.json
```
The gate is woven directly into the IL at compile time via AspectInjector. It also ships a Roslyn analyzer that fails your build if you decorate a method with `[Toggle]` but forget to add the config entry.
---
**What's in the ecosystem:**
**Three targeting strategies:**
- `UserTargetingStrategy`: gate a toggle to a named list of users via config: `"BetaFeature": "users:alice,bob"`
- `AttributeRuleStrategy`: gate by user attributes: `"PremiumDashboard": "attribute:plan equals premium"`
- `ABTestStrategy`: deterministic A/B bucketing via SHA-256, so the same user always lands in the same group: `"Experiment": "ab:50"`. Supports salts for independent experiment rounds: `"ab:50:round2"`
- `TogglesOverrides`: force any toggle ON or OFF for a specific user unconditionally, before any strategy runs. Useful for QA and support escalations.
All of these are manageable from the UI without touching config files manually.
**FtrIO.Toaster (Docker web UI):**
A self-hosted Docker UI for managing toggles live. Boolean, percentage, blue/green, user targeting lists, attribute rules, A/B percentages and salts, and per-user overrides all have dedicated controls. Every change is recorded in an audit log with user attribution.
```bash
docker compose up -d
```
**FtrIO.onetwo (CLI audit tool):**
Scans your source tree, cross-references against appsettings.json, and reports the state of every toggle with file and line number. The state model covers:
- `ON` / `OFF` — boolean state resolved from config
- `ON (BLUE)` / `OFF (BLUE)` — blue-green resolved when current slot is configured
- `BLUE` / `GREEN` — blue-green slot shown raw when current slot is not configured
- `50%` — percentage rollout
- `AB-TEST(50%)` — A/B experiment, user bucket not resolvable at audit time
- `AB-TEST(50% salt=round2)` — A/B experiment with salt
- `TARGETED(alice,bob)` — per-user targeting, not resolvable without user context
- `RULE-BASED(plan equals premium)` — attribute rule, not resolvable without request context
- `MISSING` — toggle used in code but no config entry found
Also has three experimental subcommands:
- `import`: snapshot your current flag state from LaunchDarkly, Flagsmith, or Microsoft.FeatureManagement into appsettings.json
- `migrate`: scan your codebase for existing SDK call patterns and generate a migration report showing exactly what code changes are needed
- `eject`: the reverse of migrate. Generates a complete exit report back to LaunchDarkly, Flagsmith, Microsoft.FeatureManagement, or Unleash, and can create your flags in the target system with their current values before you change a line of code. No lock-in.
**Two GitHub Actions on the Marketplace:**
- `export-manifest-action`: scans source for `[Toggle]` usage and exports a manifest of required toggle keys
- `release-check-action`: validates a target appsettings.json contains every key the release needs. Blocks the deploy if anything is missing.
The full safety net:
- Compile time: Roslyn analyzer catches missing config at build
- Deploy time: release-check-action blocks the deploy if target config is missing keys
---
**Traction so far:** 1087 NuGet downloads and 82 Docker Hub pulls, all organic.
---
**AI disclosure**
Being transparent about what AI helped with and what it didn't:
- **FtrIO core library**: written entirely by me. No AI.
- **Code comments in FtrIO**: I don't normally like comments, but I used AI to help write them here. My brain works in a scattered way and I found the comments actually make the code easier to follow for both contributors and my future self.
- **FtrIO.Toaster**: the UI was built with AI assistance.
- **Docs site**: written with AI assistance.
- **READMEs**: written with AI assistance.
- **onetwo import, migrate, and eject**: the onboarding and offboarding commands were built with AI assistance and are currently in a separate experimental branch. The core scan command is my own work.
The ideas, architecture decisions, and direction are mine. AI helped me ship faster and write clearer documentation than I would have alone.
---
**Links:**
- Core library: https://github.com/FtrOnOff/FtrIO (`dotnet add package FtrIO`)
- Toaster: https://github.com/FtrOnOff/FtrIO.Toaster (`docker compose up -d`)
- onetwo: https://github.com/FtrOnOff/FtrIO.onetwo (`dotnet tool install -g FtrIO.onetwo`)
- Docs: https://docs.ftrio.dev
- Full org: https://github.com/FtrOnOff
Happy to answer questions about any of it.
Posted Jun 23, 2026, 10:14 AM UTC