I Don't Use Feature Flags. Here's Why.
I'm going to say something that'll upset a certain type of developer: I don't use feature flags. Not in my own projects, not for most client work, not as a default approach. And my deployment frequenc
I Don't Use Feature Flags. Here's Why.
I'm going to say something that'll upset a certain type of developer: I don't use feature flags. Not in my own projects, not for most client work, not as a default approach. And my deployment frequency hasn't suffered, my code quality hasn't suffered, and my clients haven't noticed.
Before you fire up Twitter to tell me I'm doing it wrong — hear me out.
The Feature Flag Promise
Feature flags promise the ability to deploy code without releasing it. Merge your half-finished feature to main, wrap it in a flag, deploy it dark. Turn it on for internal users first. Gradually roll it out. If something breaks, flip the flag off. No rollback needed.
It sounds brilliant. And for companies like GitHub, Netflix, or Spotify — it is brilliant. When you've got 50 engineers shipping to main simultaneously, millions of users who'd notice a broken deploy, and product managers who want to A/B test everything, feature flags are essential infrastructure.
I don't work at GitHub. I probably don't work at a company like yours, either. I'm a solo developer or working with a small team. One feature at a time. A handful of deployments per day. Users who number in the hundreds or low thousands, not millions.
Different context, different tools.
What Feature Flags Actually Cost
Every feature flag adds:
Branching logic in your code. Every if (Feature::enabled('new-billing')) is a fork in your application logic. Both paths need testing. Both paths need maintaining. Both paths can have bugs. You've doubled your surface area for that feature.
A cleanup task that never happens. Be honest: when was the last time you removed a feature flag after it was fully rolled out? I've worked on codebases with flags that were "temporary" two years ago. The flag is enabled for everyone, has been for 18 months, and nobody's removed it because "it's not hurting anything." Except it is — it's cluttering the code, confusing new developers, and making the codebase harder to reason about.
A dependency on flag infrastructure. You need somewhere to store flag states. A config file, a database table, a third-party service like LaunchDarkly. That's another thing to manage, another thing that can fail, another thing that new team members need to understand.
Testing complexity. Every flag multiplies your test matrix. Feature on + scenario A. Feature off + scenario A. Feature on + scenario B. Feature off + scenario B. With three flags, you've got eight combinations. Most teams don't test all of them. The bugs hide in the combinations nobody tested.
Decision fatigue. Should this feature be flagged? What's the rollout plan? Who decides when to enable it? What's the rollback criteria? For a solo developer building a SaaS, these are questions that waste time without adding value.
The Alternative: Just Ship It
Here's my workflow:
- Create a feature branch
- Build the feature completely — UI, backend, tests, the lot
- PR, review (or self-review if solo)
- Merge to main
- Automatic deployment to production
The feature is either done and deployed, or it's on a branch. There's no half-deployed state. There's no "it's in production but turned off." The code in main is the code that's running. Always.
If a feature takes two weeks to build, it lives on a branch for two weeks. I rebase regularly against main so the merge is clean. When it's ready — properly ready, tested, complete — it gets deployed.
"But what if something goes wrong?" Then I fix it and deploy the fix. Or if it's genuinely broken, I revert the merge and deploy. Reverting a clean feature branch merge is a one-command operation. It's not slower than flipping a flag — it's exactly as fast.
"But what about getting early feedback?" Deploy it to a staging environment. I use Coolify, and spinning up a preview environment for a branch takes about two minutes. Real URL, real data (anonymised), real feedback. You don't need feature flags to get early user feedback.
The Solo Developer Context
This is the important bit that the "always use feature flags" crowd ignores: context matters.
When I'm the only developer on a project, there's no risk of someone else deploying their feature that conflicts with my half-finished work. There's no coordination problem that flags solve. I know what's in flight because I'm the one who put it in flight.
When the team is two or three people, the coordination problem is solved by a Slack message: "I'm deploying the billing update at 2pm." Done. No infrastructure needed.
Feature flags solve coordination problems. If you don't have coordination problems, you don't need them.
When I Actually Would Use Flags
I'm not dogmatic about this. There are situations where feature flags genuinely earn their keep:
Gradual rollouts to a large user base. If you've got 100,000 users and a change to the checkout flow, rolling it out to 1% first is smart risk management. Feature flags are the right tool here.
A/B testing. If you need statistical confidence that version A outperforms version B, you need both versions running simultaneously. Flags (or a proper experimentation platform) are necessary.
Kill switches for external dependencies. If your new feature relies on a third-party API that might go down, a flag that lets you disable it without a deployment is genuinely useful. I'll concede this one.
Large teams with continuous deployment. If 20 developers are all merging to main daily, flags prevent incomplete features from being exposed. This is the original use case, and it's valid.
Long-running migrations. If you're migrating from one billing system to another over three months, a flag that controls which system handles new subscriptions while old ones drain is practical.
Notice the pattern: these are all situations involving scale, risk, or multi-system complexity. If you're not in one of these situations, you probably don't need flags.
The "Best Practice" Trap
The development industry has a bad habit of taking practices from large-scale engineering teams and prescribing them universally. Feature flags, microservices, event sourcing, CQRS — all brilliant solutions to specific problems at specific scales. All unnecessary complexity for a solo developer building a SaaS with a few hundred users.
"Best practice" doesn't exist in a vacuum. It's always "best practice for this context." The best practice for deploying Netflix is not the best practice for deploying your client's e-commerce site. The best practice for a 50-person engineering team is not the best practice for you, sitting in your office, shipping code.
I've watched solo developers add LaunchDarkly to a project with 200 users because "feature flags are best practice." They spent more time managing flags than they saved in deployment risk. That's not engineering — that's cargo culting.
My Actual Setup
For the curious, here's what I use instead of feature flags:
- Git branches for work in progress
- Coolify preview environments for stakeholder feedback
- Main branch = production via automatic deployment
- Database migrations that are backwards-compatible (so I can revert code without rolling back the database)
- Quick deploys — Coolify deploys in under two minutes, so the time between "this is broken" and "this is fixed" is short
- Tests — Pest test suite runs on every PR. If the tests pass, I'm confident deploying.
It's simple. It's boring. It works. I've shipped dozens of projects this way without feature flags, and I've never once thought "I wish I had a flag for that."
The Point
Keep things simple until complexity is forced upon you. Feature flags are a tool for managing complexity at scale. If you're not operating at that scale, the flags themselves become the complexity.
Ship it or don't. Branch, merge, deploy. Your future self will thank you for the clean codebase.
I write about Laravel, AI tooling, and the realities of building software. More at stuartmason.co.uk.
Get the Friday email
What I shipped this week, what I learned, one useful thing.
No spam. Unsubscribe anytime. Privacy policy.