The Hidden Cost of 'Just Add a Flag' Feature Development
Feature flags seem like a quick fix, but they create technical debt faster than you'd think. Here's what happens when you treat them as a permanent solution.
You've been there. A stakeholder needs feature X deployed, but feature Y isn't quite ready. "Easy," someone says. "Let's just add a flag." Three months later, you're staring at 47 conditional branches in a single function, and nobody remembers which flags are still active.
Feature flags are genuinely useful for trunk-based development and canary rollouts. But when they become your default approach to managing complexity, they stop solving problems and start creating them.
The Accumulation Problem
Each flag seems harmless in isolation. One conditional here, one environment variable there. But flags don't stay isolated—they compound.
Consider this common pattern:
typescriptfunction processUserData(user: User) { if (flags.newProfileSystem) { return newProfileProcessor(user); } else if (flags.legacyProfileWithOptimization) { return optimizedLegacyProcessor(user); } else { return legacyProcessor(user); } }
Now add database migration flags, payment processing flags, notification flags. You end up with code paths that nobody fully understands. When a user reports a bug, you can't even be sure which version of the logic they encountered.
At LavaPi, we've seen teams spend weeks debugging production issues that turned out to be dormant flags interacting in unexpected ways. The "quick fix" now requires archaeology.
Testing Becomes Impossible
Your test coverage metrics look good on paper. You've got tests for both branches of every flag. But testing all combinations of flags? That's 2^n scenarios. With just 10 flags, you're looking at 1,024 possible states.
python# This looks fine in theory def test_user_profile(): assert process_user(user, flags={'newSystem': True}) assert process_user(user, flags={'newSystem': False}) # But what about this? result = process_user(user, flags={ 'newSystem': True, 'legacyOptimization': True, 'betaNotifications': True, 'newPaymentFlow': False, # ... 6 more flags })
Most teams test happy paths and a few critical combinations, then hope for the best. That's not testing—that's gambling.
Removal Is Harder Than Addition
Here's the cruel part: removing a flag requires more work than adding it.
When you add a flag, one person makes a decision. When you remove it, you need to:
- Confirm the flag is inactive everywhere
- Check for dependent flags
- Update tests (and figure out which ones actually matter)
- Coordinate with teams that might be using it
- Verify no monitoring relies on it
- Handle the code path that's becoming dead
bash# This looks simple git grep "newProfileSystem" # But what about in configs? Documentation? Team wikis? Slack threads? # What about the monitoring dashboard someone built around it? # What about the flag in production that nobody documented?
Most flags never get removed. They just become legacy baggage.
When Flags Make Sense
Feature flags aren't inherently bad. They're tools with specific, appropriate uses:
- Canary deployments: Roll out to 5% of users, measure, proceed or rollback
- Kill switches: Disable a broken feature without redeploying
- A/B testing: Temporary, time-bounded experiments with clear success metrics
- Incomplete features: Temporarily hiding work in progress during active development
The distinction matters. A flag that's meant to be temporary is operationally different from one that's become permanent infrastructure.
The Better Approach
Instead of asking "should we add a flag?", ask "what happens when this needs to be removed?" If the answer is "we're not sure," it's not a flag problem—it's a design problem.
If you need to ship incomplete work, that's legitimate. But set a removal deadline. Make someone responsible for cleanup. Treat flag removal like you treat technical debt—as a first-class concern.
The "just add a flag" approach works until it doesn't. And when it breaks, it breaks silently, in production, at 2 AM.
LavaPi Team
Digital Engineering Company