You're reading "CI/CD: Flagging Productivity", written on February 1, 2026.
CI/CD: Flagging Productivity
If you are serious about CI/CD, your system must tolerate unfinished work in production.
That sentence might make people uncomfortable, but the alternative is worse. If incomplete functionality cannot safely exist in production, then integration must wait until a feature is “done.” The pipeline slows down, commits pile up, and integration becomes a periodic event instead of a continuous one.
At that point the C in CI is like… “C u l8r!” Haha… Ha.
Feature flags solve this problem directly. They allow code to be deployed while the behavior remains disabled. Deployment and release become separate decisions. The pipeline keeps moving, while visibility of the feature remains under explicit control.
If you are unfamiliar with the pattern, the classic explanation by Martin Fowler is still the best place to start:
https://martinfowler.com/articles/feature-toggles.html
Feature flags are often described as rollout tools. That framing undersells them. In practice they are one of the structural mechanisms that allow CI/CD to function without freezing development.
Use Flags When Change Cannot Be Atomic
Not every change can land in a single step.
Replacing a subsystem, migrating data flows, or introducing a new execution path often requires weeks of incremental work. The old behavior must remain operational while the new one gradually takes shape.
Without feature flags, the pressure to keep production stable pushes that work out of the integration stream. Developers isolate it until the moment everything is ready to land at once.
That approach trades many small integrations for one large one, which is exactly the opposite of what CI/CD is trying to achieve.
Feature flags allow the new implementation to integrate continuously while the existing behavior remains active. The system stays deployable, the pipeline keeps flowing, and the switch between implementations becomes an operational decision rather than a risky deployment event.
If CI/CD is about small, safe steps, feature flags are what make those steps possible during long transitions.
Do Not Use Flags by Default
Feature flags are powerful, but they are not free.
Each flag introduces additional execution paths that must remain correct. Tests must consider both states. The code becomes temporarily more complex until the flag is removed.
Because of that cost, flags should be used where they actually provide leverage: situations where behavior must transition gradually or where switching implementations needs operational control.
In many cases a simpler strategy works better. Dark launching infrastructure, extending existing behavior instead of replacing it, or introducing parallel systems that are not yet connected to user-visible paths often avoids the need for a flag.
Flags should solve a real deployment constraint. They should not become the default solution for every new feature.
Manage the Lifecycle or They Become Debt
Most teams that use feature flags still handle them carelessly. And I’ve been those teams, I know how it goes.
Flags get added during development, remain enabled after rollout, and then quietly live in the codebase forever. Eventually the system accumulates a forest of conditional paths that nobody fully understands.
This is not an inevitable outcome. It is a lifecycle problem.
A healthy workflow treats feature flags as temporary artifacts with a clear path to removal. Creating a feature that requires a flag should introduce the scaffolding deliberately. Tests should cover the system with the flag both enabled and disabled. Once the feature is fully released, removing the flag should be part of the normal cleanup process.
If the lifecycle is ignored, you can indeed end up with a bit of an unholy mess on your hands.
Reduce the Burden With Better Tooling
One reason flags are neglected is that the surrounding work is mechanical.
Developers must create configuration entries, wire conditional paths, write tests for both states, and eventually remove the toggle when it is no longer needed. None of that work is difficult, but it is repetitive, which makes it easy to postpone.
This is exactly the kind of task that modern tooling can help with. Development workflows can generate flag scaffolding automatically, enforce testing across flag states, and detect when flags have outlived their purpose.
Pick a service provider - Unleash if you want to keep it in-house, Launch Darkly if you want to offload - and get comfortable using the APIs in your automation. Unfortunately, there isn’t any off the shelf tooling I’m aware of at the moment that will just take care of this, at least until Atlassian decides to stitch a flag service to its offerings or their LaunchDarkly integration deepens.
Large language models are particularly effective at assisting with this pattern because the work is structured and repetitive. LLMs can further help by reducing the ramp up time for developers who - having never used feature flags before - have no idea how to insert them into code.
Feature flags will always introduce some complexity. The goal is not to eliminate that cost, but to keep it small enough that continuous deployment remains the easier path.
Because without the ability to hide unfinished work, CI/CD eventually stops being continuous.