Feature Flags vs Config Files - When to Use Which (2026)
Config files and feature flags both control behavior without a code change, but they solve different problems. Here's how to tell them apart, and when a flag service beats a config file.
Published:
Both a config file and a feature flag let you change how software behaves without editing code. That’s why people confuse them. And it’s why teams sometimes reach for the wrong one - shipping a redeploy for something that should have been a runtime flip, or wiring up a whole flag service for a setting that never changes.
They solve different problems. A config file changes with a deploy. A feature flag changes while the app is running. That one difference decides almost everything. This guide walks through where each belongs, and when a config file stops being enough.
What a config file is good at
A config file holds settings that are scoped to a deploy and an environment. Database URLs. Timeouts. Log levels. Third-party API endpoints. The environment name. Build constants.
These share three traits. They change rarely. They apply to the whole app, not a subset of users. And they’re naturally tied to a release - you don’t change your production database host at 2pm on a Tuesday without a deploy, and you wouldn’t want to.
For that kind of setting, a config file is simpler and correct. If it’s environment-level, rarely changes, and never needs per-user targeting, it belongs in config. Adding a flag service for it is pure overhead.
What a feature flag is good at
A feature flag is a switch you control at runtime, without a deploy, often for a slice of users.
That unlocks things a config file can’t do:
- Flip without a deploy. Turn a feature on or off from a dashboard in seconds, no release in the loop.
- Target a subset. Roll a feature out to 1% of users, or to internal staff, or to one region.
- Kill switch. When something breaks, flip it off instantly instead of rolling back a deploy.
- Audit trail. See who changed what flag, when, and why.
None of those are a config file’s job. The moment you need one of them, you’ve outgrown the file.
The line: does it change while the app runs?
Here’s the clean test. Ask one question of any setting: does it need to change while the app is running, without a deploy?
If no, it’s config. Ship it in the file. If yes, it’s a flag. It belongs in a flag service.
A permanent architecture choice - which payment provider you use, your database connection string - is config, because it changes with a deliberate release or never. A release you want to roll out gradually, or kill instantly if it misbehaves, is a flag, because the whole value is changing it live.
The trap: config files pretending to be flags
The failure mode is using a config file as a crude flag. A boolean in a YAML file, redeployed every time you want to flip it.
It works for the first few. Then it breaks. You can’t roll out to 10% of users from a boolean. You can’t flip it without a deploy, so your “kill switch” takes a full release to fire - useless in an incident. There’s no audit trail. And as the number of these grows, your config file becomes a pile of half-documented toggles nobody dares touch.
The redeploy is the tell. If you’re shipping a deploy just to change a value, that value wanted to be a flag.
When you cross the line: which flag tool
Once you’ve decided something is a flag, you need somewhere to store and serve it - and this is where flag state must live outside your build. If flag values sit in a file you redeploy to change, you’ve reinvented the config file and lost the runtime benefit. Flag state belongs in a service every running instance reads live.
Three options, by what you’re optimizing for:
Depth, if you can absorb the cost. LaunchDarkly is the deepest option - advanced targeting rules, guarded releases that automatically roll back on a bad metric, around 38 SDKs. The trade is its pricing: $10 per service connection per month plus $8.33 per 1,000 client-side monthly active users, charged on your highest-volume context kind, which surprises teams that estimate from headcount. Model your real context volume first.
Flat, predictable pricing. ConfigCat is the closest thing to a config file with runtime superpowers, and its pricing fits the mental model. It charges no per-seat and no per-MAU fee - MAUs, contexts and flag reads are unlimited on every tier - and you pay by config-download volume instead. Forever Free gives 10 flags and 5M downloads a month; Pro is $110. The one thing to watch, fittingly, is polling: a chatty SDK can push you across a download tier without adding a single user, so cache aggressively and use the SDK proxy.
Self-hosting in your own infra. Unleash is the strongest open-source pick - AGPL-3.0, self-hostable including air-gapped, with activation strategies, gradual rollouts and kill switches in the free edition. The gotcha: RBAC, SSO/SAML and SCIM are all Enterprise-gated, and there’s no read-only viewer seat, so once non-engineers need access it’s $75 per seat per month with a 5-seat minimum.
Use both, on purpose
The answer isn’t flags instead of config. Mature systems run both, deliberately.
Config files hold the deploy-scoped, environment-level settings that rarely change - connection strings, endpoints, build constants. Feature flags hold the runtime decisions that change often, target users, and need instant reversal - new features, experiments, kill switches.
The skill is knowing which layer a setting belongs in. Put a runtime decision in config and you’ll redeploy for every change. Put an environment constant behind a flag service and you’ve added a network dependency and a bill for nothing.
So which is it?
- Environment-level, rarely changes, no targeting - config file. Keep it simple.
- Runtime change, targeting, gradual rollout, or a kill switch - feature flag. Use a service, not a file.
- You want depth and can forecast the cost - LaunchDarkly.
- You want flat, headcount-independent pricing - ConfigCat, and watch your polling.
- You want to self-host in your own infra - Unleash, if you can live inside the open-source feature set.
Ask the one question - does it change while the app is running - and the answer falls out. Config for the deploy-time constants, flags for the runtime decisions, and never a redeploy for something that should have been a switch.
Tool pricing and features verified against each vendor’s site on 26 July 2026. Feature-flag pricing changes often - we re-verify regularly. LaunchDarkly contract figures cited elsewhere are from Vendr’s third-party buyer data and attributed as such.
Frequently Asked Questions
What's the difference between a feature flag and a config file?
A config file holds settings that change with a deploy - database URLs, timeouts, environment names. A feature flag is a switch you can flip at runtime, without a deploy, often for a subset of users. Both change behavior without editing code, but the config file needs a release to take effect, while the flag changes instantly from a dashboard or API. If you need to change it while the app is running, it's a flag's job.
Can't I just use a config file as a feature flag?
You can for the simplest cases - a boolean in a config file that you redeploy to change is a crude flag. It breaks down fast, though. You can't target a percentage of users, you can't flip it without a deploy, you have no audit trail, and there's no instant kill switch when something breaks. The moment you need runtime changes, per-user targeting, or gradual rollouts, a config file stops being enough and a flag service earns its place.
Do feature flags replace config files?
No, they complement each other. Config files still handle deploy-time, environment-level settings that rarely change and don't need targeting - connection strings, feature toggles that are permanent architecture choices, build constants. Feature flags handle runtime decisions that change often, target users, and need instant reversal. Most mature systems use both, and the skill is knowing which layer a given setting belongs in.
When is a config file better than a feature flag?
When the setting is environment-level, rarely changes, and never needs per-user targeting or runtime flipping - database hosts, log levels, third-party API endpoints, static build constants. These belong in config because they're deploy-scoped by nature and adding a flag service for them is pure overhead. Reach for a flag only when you need runtime control, targeting, or gradual rollout. Otherwise the config file is simpler and correct.
Explore More
Tool Reviews
Related Articles
- Feature Flags in Python, Done Right - A 2026 Tutorial for Flask and Django
- Feature Flags in Go, Done Right - A 2026 Tutorial With Real SDK Code
- Feature Flags in Java and Spring, Done Right - A 2026 Tutorial
- 4 ConfigCat Alternatives When Traffic Tier Jumps Bite (2026)
- Feature Flags vs Feature Toggles - Are They the Same Thing? (2026)
Free Newsletter
Get the Feature Flags Newsletter
Platform benchmarks, real pricing data and progressive delivery practice. No spam.
Related Articles
Feature Flags in Python, Done Right - A 2026 Tutorial for Flask and Django
A hands-on guide to implementing feature flags in Python, from a hand-rolled dict toggle to production SDKs in Flask and Django. Real illustrative code and honest trade-offs.
July 28, 2026
how-toHow to Calculate Sample Size for A/B Testing (2026 Guide)
Sample size decides whether your A/B test can find a real effect. Here is the formula, a worked example, the four levers that move it, and why halving your MDE quadruples the traffic you need.
July 28, 2026
how-toHow to Choose Metrics for A/B Testing - Primary, Secondary and the OEC (2026)
Most failed A/B tests fail at metric selection, not analysis. This guide shows how to pick one primary metric, structure secondary and guardrail metrics, avoid vanity metrics, and build an Overall Evaluation Criterion you can trust.
July 28, 2026
LaunchDarkly Review
ConfigCat Review
Unleash Review