Why We Default to Trunk-Based Delivery
Long-lived branches are a debt you pay with interest. Here is why every pipeline we build defaults to trunk-based delivery, and what that actually looks like in practice.
Most of the CI/CD pain we inherit traces back to the same root cause: branches that live too long. The merge that should have taken a minute takes an afternoon. The release nobody wants to cut on a Friday. The conflict that surfaces a decision made three weeks ago by someone who has since moved teams.
Trunk-based delivery is not a tool you install. It is a constraint you adopt — and almost everything good about a delivery pipeline follows from it.
The problem with long-lived branches
When a branch lives for more than a day or two, it begins to drift from the trunk. Every commit on main is a commit the branch has not seen. The longer it lives, the larger the eventual reconciliation, and the more of that reconciliation happens at the worst possible time: right before a release, when everyone is already under pressure.
The hidden cost is not the merge conflict itself. It is the batch size. A branch that accumulates two weeks of work ships two weeks of risk in a single event. When something breaks, you are bisecting across dozens of changes instead of one.
Small batches are not a nicety. They are the single highest-leverage change most teams can make to their delivery reliability.
What trunk-based delivery actually means
In practice, it comes down to a few non-negotiables:
- Every change merges to trunk within a day, behind a feature flag if it is not ready to be seen.
- Trunk is always releasable. CI on
mainis a release candidate, not a suggestion. - Releases are decoupled from deploys. You deploy continuously and release with a flag flip.
That last point is what makes the whole thing safe. Deploying code and exposing a feature become two separate decisions, made by two different mechanisms, reversible independently.
The pipeline that supports it
Trunk-based delivery only works if the pipeline earns the team's trust. That means:
# every merge to main runs the same gate
test → build → scan → deploy (canary) → promote
- A fast, reliable test suite — flaky tests are a trunk-based killer, because they erode the assumption that green means safe.
- Progressive delivery — canary or blue/green, so a bad change is caught by a fraction of traffic, not all of it.
- One-command rollback — if promotion goes wrong, recovery is a single, boring, well-rehearsed action.
Where teams get stuck
The most common objection is "our code is not ready to be on trunk." That is what flags are for. The second is "our tests are too slow to run on every merge." That is a problem to fix, not a reason to batch — and build caching usually cuts CI time by 40 to 80 percent without touching the tests themselves.
Trunk-based delivery feels riskier right up until the moment it is in place. Then the Sunday deploy window disappears, the merge conflicts shrink to nothing, and shipping becomes the least interesting part of the week. Which is exactly the point.