Feature flags: best practices, and seven anti-patterns to avoid
What is a feature flag? Four types of toggles, what to try before adding one, and seven anti-patterns that end up running code nobody has tested.
12 min read
Sébastien Nobour
Founder of DEVEDANOS
Trunk-based development fits in one sentence: everyone integrates their work into a single branch, several times a day. What makes it sustainable fits in another: a fast deployment pipeline whose verdict is final.
AI agents that write and commit code do not change these rules. They make them more necessary.
Trunk is the main branch, also called main or mainline. In trunk-based development, every developer merges their work into it at least once a day, sometimes several times. If they create branches, those usually last a few hours at most, and the team has no more than three active at once. A feature branch, by contrast, carries days or weeks of work (DORA, “Trunk-based development”).
MinimumCD makes it a minimum condition of continuous integration: work is integrated into trunk at least once a day.
Farley goes further. His ideal branching strategy comes down to two words: “Don’t Branch!” If branches exist at all, they should be tiny, few in number and short-lived, merged at least once a day. When a team is working well, it merges every 10 or 15 minutes (Continuous Delivery Pipelines, 2021, p. 44).
So the difference is not about the tool. It is about how long a change lives apart from everyone else’s.
A long-lived branch delays integration. While it lives, trunk moves on without it, and it moves on without trunk. The two drift apart. On merge day, everything that changed on both sides has to be reconciled.
Humble and Farley describe the promise and what becomes of it. The promise: go faster by making big changes on a branch, then merge it all back at the end. In practice, merging back is what becomes the hard part, and the bigger the change, the harder the final merge. They sum it up in one line: the more compelling the reason for creating a branch seems, the less you should do it (Continuous Delivery, 2010, p. 349). They also note that an application whose work happens on branches is not being continuously integrated (p. 347).
DORA links trunk-based development to better software delivery and operational performance, based on its 2016 and 2017 data. The same programme recommends having no code freeze and no integration phase (“Trunk-based development”).
A short-lived branch is also a small change.
Integrating several times a day only holds up if each integration is checked quickly. That is the job of the deployment pipeline.
The commit stage compiles the code, runs the fast tests, and gives the developer its verdict in under 5 minutes (Continuous Delivery Pipelines, pp. 52 and 121). If it passes, it produces the release candidate: the exact unit that will end up in production, if it gets that far (p. 58).
This candidate is built only once. Humble and Farley explain why: rebuilding at each stage risks putting something into production other than what was tested (Continuous Delivery, pp. 113 and 114).
The candidate is stored in an artifact repository. Farley calls it the version of truth: what it holds are the exact bits and bytes we intend to deploy into production. Environment-specific configuration is kept separate from it, and no version is built for a particular environment (Continuous Delivery Pipelines, p. 60).
The acceptance stage takes this candidate and always follows the same four steps: configure the environment, deploy the candidate, check that it starts, run the acceptance tests (p. 65). Manual testing is exploratory. They only cover candidates that have already passed acceptance, and they are not used for regression testing (pp. 73 and 74).
MinimumCD sums up these rules. The pipeline is the only way to deploy to any environment. The artifact is immutable: no human changes after the commit. The pipeline decides whether a change can go to production, and its verdict is final.
Here is the principle, written as pseudo-configuration, with no tool syntax:
# Pseudo-configuration written for this article: the principle, not a tool.
pipeline:
trigger: every commit to trunk
commit stage:
target duration: under 5 minutes
do:
- compile
- run the fast tests
- build the candidate, once only
- store the candidate in the artifact repository
on failure: stop the line
acceptance stage:
exclusive: the whole stage, from first step to last
candidate: the most recent one that passed the commit stage
do:
- configure the environment
- deploy the candidate
- check that it responds
- run the acceptance tests
- shut down the environment
on failure: stop the line
production:
candidate: the one that passed acceptance
release: decided by a person (Continuous Delivery)
or automatic (Continuous Deployment)
A red pipeline means one thing: trunk is no longer ready for production. Farley makes this the team’s priority: keeping the path to production clear (Continuous Delivery Pipelines, p. 57). MinimumCD puts it more bluntly: when the main pipeline is red, all feature work stops.
Humble and Farley call this stopping the line: if any part of the pipeline fails, you stop (Continuous Delivery, p. 119).
Then there are only two options. Fix it within about ten minutes, or revert the change (Continuous Delivery Pipelines, p. 56). And if the author of the change is not around, the team reverts it for them (p. 57).
git switch main && git pull
git revert --no-edit <offending-commit>
git push
The revert is a commit in its own right. It goes through the pipeline like any other, and the history keeps a record of what happened.
The DORA 2024 report measured something its authors did not expect. When AI adoption increases by 25%, delivery throughput drops by an estimated 1.5% and delivery stability by an estimated 7.2% (Accelerate State of DevOps 2024, pp. 39 and 40). These are estimates drawn from a survey: a correlation, not proof of causation.
The authors put forward a hypothesis. AI makes it possible to produce far more code in the same amount of time. So it is possible, and in their view even likely, that change size goes up. And their data has shown for years that large changes are slower and more often a source of instability (p. 40).
If the hypothesis holds, the answer is not a new tool. It is the discipline of small batches, applied to agents as to humans. DORA in fact describes working in small batches as a safety net for AI adoption (“Working in small batches”).
MinimumCD draws concrete rules for agents from this (“Agentic CD”):
So an agent has no more rights than a developer. The pipeline remains the only path to production.
That leaves code review. Bryan Finster, a maintainer of MinimumCD, argues in “AI broke your code review, here’s how…” for reserving human judgement for what actually needs it: the behaviour the team defines before the code, the scenarios turned into acceptance tests, the team’s own knowledge, and compliance. In a LinkedIn post on 24 September 2026, he describes one of his best teams. No code review held up delivery: “Our pipelines reviewed the code.”
In our article on building an app with AI, we explain what AI does well on its own, and what it needs around it for an application that holds up in production.
More commits means more candidates. What happens when the acceptance stage is busy and new candidates keep arriving?
Humble and Farley answer with an example (Continuous Delivery, pp. 118 and 119, figure 5.6). The acceptance tests are running on candidate 1. Meanwhile, other changes arrive and pass the commit stage. The pipeline does not start a second run of the acceptance tests, since they are already running. Nor does it queue the candidates: if it tested them all, it would fall further and further behind what the developers are doing. When acceptance frees up, it takes the most recent candidate, here number 5. Candidate 2 is never tested on its own. On a single trunk, candidate 5 contains its changes.
Farley describes the same mechanism eleven years later, on a financial exchange whose development he led. Acceptance took under 40 minutes, and during that time the commit stage produced around ten candidates. When the acceptance stage freed up, the most recent candidate was deployed. Changes were batched together this way, and acceptance did not build up a backlog it would never have cleared (Continuous Delivery Pipelines, p. 131).
Second rule: the acceptance stage is exclusive as a whole. Its four steps run back to back on the same candidate (Continuous Delivery Pipelines, p. 65). Humble and Farley describe an instance of the system created clean at the start of the acceptance test run, used by all those tests, then shut down at the end (Continuous Delivery, pp. 219 and 220).
If you reserve only the deployment, and not the whole sequence, another candidate can be deployed between the first one’s deployment and its tests. The test results then carry one candidate’s name but validate another.
Integrating several times a day means committing code that is not finished. Humble and Farley give three ways to keep trunk ready for production despite that (Continuous Delivery, pp. 347 to 349):
The feature toggle comes after these techniques, when none of them is enough. We go into when it is justified, and the mistakes that make it dangerous, in our article on feature toggles.
We work on a single trunk, with a pipeline that gives its verdict on every commit. AI is one of our tools, within an approach where every change is checked by automated tests.
For custom software development, we work on a fixed budget, invoiced at the end of each month for the work done. Your application is usable within a month. Your teams use it from the first month, and that use decides what we develop the following month.
And to make sure that what worked last month still works this month, we apply the Zero-Regression Guarantee: every regression is fixed and covered by an automated test so that it does not come back, at no extra cost.
In our guide, you will find the questions to ask before signing a software development quote.
Do you need software built, and want it built this way? Shall we talk?
What is a feature flag? Four types of toggles, what to try before adding one, and seven anti-patterns that end up running code nobody has tested.
How much should you budget to build an app? The figure alone is not enough: aim for a goal rather than a feature list, with users from the first month.
Predictive or adaptive approach? The real dividing line is not between waterfall and agile. It runs between predicting and adapting. What that means for software.