how-to

Trunk-Based Development - A Practical Guide With Feature Flags (2026)

Trunk-based development only works if you can ship unfinished code safely. Here's how to do it with feature flags, step by step, and which tools fit each team size.

Published:

Trunk-based development sounds simple. Everyone commits to one branch, usually main, at least once a day. No long-lived feature branches drifting for weeks. No merge hell on release day.

Then you hit the obvious problem. If everyone merges to the branch you deploy from, how do you merge code that isn’t finished yet?

That’s the whole puzzle. And the answer, in practice, is feature flags. This guide walks through how to actually run trunk-based development with flags, the traps that catch teams, and which tools fit at each size.

Why trunk-based development needs feature flags

Long feature branches rot. They drift from main, and every day the drift gets harder to merge back. A branch open for three weeks is a three-week merge conflict waiting to happen.

Trunk-based development fixes that by forcing daily integration. But it creates a new demand. When you commit unfinished work to trunk, that work will ship to production on the next deploy. You can’t have a half-built checkout flow going live to customers.

A feature flag is the switch that lets unfinished code ship turned off. You wrap the new code in a flag, keep it disabled in production, and merge freely. The code is on trunk, integrated with everyone else’s, but invisible to users until you flip it on. This is called shipping dark, and it’s the mechanic that makes the whole model work.

Step 1: Set your merge discipline

Before any tooling, agree on the rule. Every developer merges to trunk at least once a day. Short-lived branches are allowed, but they live for a day or two, not a week.

Small merges are the point. A 40-line change is easy to review, easy to revert, and rarely conflicts. A 2,000-line branch is none of those. The smaller and more frequent your merges, the less trunk-based development can hurt you.

Step 2: Wrap every unfinished feature in a flag

Now the code discipline. Any change that isn’t complete, or that you don’t want live yet, goes behind a flag. The pattern is the same everywhere:

  1. Create the flag in your flag tool, defaulted to off.
  2. Wrap the new code path in a check - if the flag is on, run the new path, otherwise run the old one.
  3. Merge to trunk. The flag is off in production, so nothing changes for users.
  4. Keep merging as you build, all behind the same off flag.

For teams that want this managed for them, LaunchDarkly is the deepest option - advanced targeting, guarded releases that automatically roll back when a metric goes bad, and around 38 SDKs so almost any stack is covered. The catch is the bill. It charges $10 per service connection per month plus $8.33 per 1,000 client-side monthly active users, and it charges on your highest-volume context kind, so device and anonymous-session counts can blow past your user count. Price your real context volume before you commit.

Step 3: Roll the flag out gradually

Once the feature is built and tested behind the flag, you don’t flip it to 100% for everyone at once. You roll it out.

Start with your own team. Then 1% of users. Watch the metrics. Then 10%, 50%, 100%. If anything breaks, flip the flag off - no redeploy, no rollback, no incident. The flag turns a scary release into a dial you can turn down instantly.

If you want to run this in your own infrastructure rather than a vendor’s cloud, Unleash is the strongest self-hosted option. It’s open source under AGPL-3.0, self-hostable including air-gapped, and its free edition includes activation strategies, gradual rollouts, kill switches and canary - exactly the rollout controls trunk-based development needs. The gotcha to know upfront: RBAC, SSO/SAML and SCIM are all gated to paid tiers, and there’s no read-only viewer seat, so once non-engineers need access, every one is a paid seat at $75 per seat per month with a 5-seat minimum.

Step 4: Keep flag config out of your deploys

Here’s a subtle point that trips teams up. If your flag values live in a config file that you have to redeploy to change, you’ve lost half the benefit. The whole value of a flag is flipping it without shipping code.

So flag state belongs in a flag service, not in a file baked into your build. You change the flag in a dashboard or an API call, and every running instance picks it up in seconds. No deploy in the loop.

For a team on a budget that still wants this properly, Flagsmith is the cheapest serious entry. It’s open source under BSD-3-Clause with genuine self-hosting, its free cloud tier gives 50,000 requests a month with unlimited flags, and paid Start-Up is just $40 a month on annual billing. The honest trade-off is that self-hosting its Django and Postgres stack is real DevOps work, and A/B testing is basic rather than a full statistics engine. For flags-first trunk-based development, that’s usually fine.

Step 5: Delete flags on a schedule

This is the step everyone skips, and it’s the one that quietly kills the model.

Every release flag is temporary debt. Once a feature is fully rolled out and stable, the flag has done its job. The if check and the old code path are now dead weight. Leave them and, over a year, your codebase fills with stale toggles nobody remembers the purpose of.

Treat flag cleanup as part of finishing a feature, not a someday chore. Tag each release flag with an owner and an expiry date. Review your flag list every sprint. Delete the ones whose features are done. A flag tool with a clear dashboard makes this visible, which is half the battle.

Trunk-based vs feature branches: when to switch

To be fair to the other side, long-lived feature branches aren’t always wrong. If your team is small, ships rarely, and doesn’t practice continuous integration, the overhead of flags might not pay off yet.

But the moment you have more than a handful of developers integrating regularly, feature branches start costing more than they save. Merge conflicts scale with branch age and team size. Trunk-based development, with flags doing the safety work, scales better.

So which setup should you pick?

  • You need the deepest rollout tooling and can forecast the cost - LaunchDarkly, for guarded releases and automatic rollback. Just model your highest-volume context kind first.
  • You want to run flags in your own infra - Unleash, if you can live inside the open-source feature set and don’t need free SSO.
  • You want cheap, transparent, open-source flags - Flagsmith, the lowest-cost serious entry, with real DevOps work as the trade for self-hosting.

The tool matters less than the habits. Merge small, merge daily, wrap the unfinished work in a flag, roll it out gradually, and delete flags when they’re done. Get those five right and trunk-based development stops being scary and starts being the calmest way your team ships.


Tool pricing and features verified against each vendor’s site on 26 July 2026. Feature-flag pricing changes often - we re-verify regularly. Contract figures cited for LaunchDarkly are from Vendr’s third-party buyer data and attributed as such.

Frequently Asked Questions

What is trunk-based development?

It's a branching model where every developer commits to one shared branch (the trunk, usually main) at least once a day, instead of working on long-lived feature branches. Short-lived branches are fine, but they merge back within a day or two. The goal is to avoid big, painful merges and keep the whole team integrating continuously.

Why do you need feature flags for trunk-based development?

Because you're merging unfinished work into the branch you deploy from. A feature flag wraps the incomplete code and keeps it switched off in production, so it ships dark and hurts nobody. Without flags, trunk-based development forces you to either hold merges until a feature is fully done, or ship half-built features live. Flags are what make committing to trunk daily actually safe.

Is trunk-based development better than feature branches?

For most teams practicing continuous integration, yes. Long-lived feature branches drift from main and create merge conflicts that grow with time. Trunk-based development trades that for daily integration and small, reviewable commits. The cost is discipline - you need feature flags, solid tests, and the habit of merging small. If your team can't commit to that discipline, feature branches may feel safer at first.

How do you clean up feature flags in trunk-based development?

Treat every flag as temporary debt. When a feature is fully rolled out and stable, delete the flag and the dead code path within a sprint or two. Flags that outlive their purpose become stale toggles nobody understands. Set a review cadence, tag release flags with an owner and an expiry, and remove them on schedule. The discipline of cleanup is as important as the discipline of merging small.

Explore More

Free Newsletter

Get the Feature Flags Newsletter

Platform benchmarks, real pricing data and progressive delivery practice. No spam.

Free. Unsubscribe any time. See our privacy policy.

Related Articles