Nguyen Le PhongNguyen Le Phong

Trunk-Based Development

A practical introduction to trunk-based development: small frequent merges, feature flags, fast tests, code review discipline, and the team habits needed to keep the main branch healthy.

The merge conflict started with a file that looked innocent. Two branches had touched the same function for different reasons. One added a new validation rule. The other changed the shape of the response. Both changes were reasonable. Together, after several days apart, they created a small puzzle nobody wanted to solve near the end of the sprint.

Trunk-based development is partly a response to that kind of pain. The idea is simple: developers integrate small changes into the main branch frequently instead of working for a long time on separate branches. The trunk, usually main or master, remains the shared line of development. Work may happen in short-lived branches, but those branches are measured in hours or a couple of days, not weeks.

The promise is faster feedback. When changes land often, conflicts are smaller, integration problems appear earlier, and the team sees the real state of the system sooner. Continuous integration becomes meaningful because there is one branch that represents current truth. The main branch is not a ceremony. It is the place where the team keeps learning together.

This does not mean everyone pushes unfinished behavior directly to users. That is the common misunderstanding. Trunk-based development depends on techniques that separate code integration from feature release. Feature flags, branch by abstraction, dark launches, configuration switches, and backward-compatible changes allow code to merge before the full product behavior is visible. The code can be present while the feature remains controlled.

Small changes are the foundation. A pull request that changes one boundary, one testable behavior, or one preparatory refactor is easier to review and safer to merge. Large branches create delayed risk. They may feel safer because they keep unfinished work away from trunk, but they often store integration cost like a debt that comes due later.

Fast tests are non-negotiable. If the main branch is shared truth, the team needs quick confidence that it still works. Unit tests, focused integration tests, linting, type checks, and a small set of critical end-to-end tests form the minimum safety net. Slow or flaky pipelines make people avoid merging, and the whole practice starts to decay.

Code review also changes. Reviewers need to respond quickly because long waiting time turns short-lived branches into long-lived branches. The review standard should stay high, but the unit of review becomes smaller. Instead of asking one pull request to explain the whole feature, each pull request explains one safe step. The design may live in a separate note, while the code lands in slices.

Feature flags deserve respect. They are not just if statements. A team needs naming conventions, owners, cleanup habits, observability, and a clear plan for removing old flags. Otherwise trunk-based development can trade branch mess for flag mess. The discipline is not only merging quickly. It is keeping the production codebase understandable while unfinished work moves through it.

Trunk-based development also asks for trust. Developers must believe that the team will keep trunk healthy, fix broken builds quickly, avoid hiding risky work, and communicate when a change affects others. A broken main branch is not one person's embarrassment. It is a team interruption. The mature response is to repair the signal, learn why it happened, and strengthen the guardrail.

Some teams are not ready to jump all at once. That is fine. A calmer path is to shorten branch lifetime first, then improve tests, then introduce feature flags for one kind of change, then measure how often work integrates. The goal is not to win a process argument. The goal is to reduce late integration surprise.

The question behind trunk-based development is: how long can we afford to be away from the truth? The longer a branch lives, the more it becomes a private version of reality. Frequent integration brings the team back to shared reality sooner, while the work is still small enough to adjust.

If your team has moved from long-lived branches to trunk-based development, I would be interested in what changed first: merge conflicts, review rhythm, test discipline, or the way people talked about unfinished work.

Qu'en avez-vous pensé ?