A branching model where teams collaborate on a single trunk branch with short-lived branches, enabling fast, safe releases.
A branching model where teams collaborate on a single trunk branch with short-lived branches, enabling fast, safe releases.
Lesson outline
Trunk-based development (TBD) is a source-control model where everyone integrates changes into a single branch (often called trunk or main) frequently—ideally at least once every 24 hours.
Instead of long‑lived feature branches, teams use very short‑lived branches or commit directly to trunk. CI runs on every change so trunk is always in a releasable state.
TBD is a key enabler of Continuous Integration and Continuous Delivery: small, frequent, well‑tested changes reduce risk and keep releases boring.
Core ideas
Snapshot of your project at a point in time
Parallel line of work; merge when ready
Full log of commits; revert or compare anytime
In trunk-based development, everyone integrates to a single main branch and aims to **commit to trunk at least once every 24 hours**. Small, frequent changes keep the branch green and releasable.
Trunk/main is the single shared integration branch. All production releases ultimately come from this branch.
Developers either commit directly to trunk (very small teams) or use short‑lived feature branches that last hours or a couple of days at most.
Each branch/commit triggers CI: build, tests, linting, and security checks. Changes only land on trunk when the pipeline is green.
Example Git commands in a TBD workflow
# Start a short-lived feature branch git checkout -b feature/tbd-dashboard # Commit small, focused changes git add . git commit -m "Add TBD lesson outline" # Sync with latest trunk before opening PR git checkout main git pull origin main git checkout feature/tbd-dashboard git rebase main # Push and open PR targeting trunk/main git push -u origin feature/tbd-dashboard
The goal is many small branches like this that live for hours or a couple of days—not weeks.
Git Flow uses many long‑lived branches (main, develop, release/*, hotfix/*). Work often spends days or weeks in isolation before being merged. This creates merge conflicts and slows down releases.
Trunk-based development keeps a single mainline (trunk) and uses short‑lived branches purely for code review. The goal is to integrate early and often, avoiding "merge hell."
In practice, TBD trades some up‑front discipline (tests, CI, feature flags) for much faster feedback and simpler release pipelines—especially for modern cloud and microservice systems.
Git Flow vs Trunk-Based Development
Traditional
Multiple long‑lived branches (main, develop, release/*, hotfix/*). Features live on branches for days or weeks before merging.
In practice
Recommended
Single mainline (trunk / main) plus short‑lived feature branches. Branches live hours or 1–2 days; merge as soon as CI + review pass.
In practice
Detailed comparison
Pros: Faster time to production, fewer merge conflicts, simpler git history, better continuous integration habits, and easier automation around deploys and rollbacks.
Pros: Encourages small, focused pull requests that are quicker to review, and works well at scale (large codebases, many teams) when paired with strong tests and automation.
Cons: Requires good test coverage, a reliable CI/CD pipeline, and strong team discipline. Incomplete features must be hidden behind feature flags or branch‑by‑abstraction instead of lingering on long‑lived branches.
On a 2–5 person team, the simplest TBD workflow is committing directly to trunk. Everyone runs tests locally before pushing; the CI pipeline confirms the build is healthy.
Because commits are frequent and small, issues are easy to trace and revert. The team can deploy directly from trunk multiple times per day without complex branching.
This works best when the codebase is well‑tested and the team treats a broken main branch as an emergency that must be fixed before new work continues.
Dev commits
Small, frequent commits
Trunk
Single shared mainline
CI: build + test
Red build stops new work
Deploy
Deploy from trunk multiple times per day
Larger teams still use trunk as the single integration branch, but they introduce short‑lived feature branches (lasting hours to a couple of days) to support code review.
Each branch contains one focused change and is owned by a single developer or pair. A pull request targets trunk, triggers CI, and is merged as soon as tests and review pass.
Branches are deleted immediately after merge. Keeping branches small and short‑lived avoids divergence and reduces the risk of painful merges.
Short‑lived feature branch
Hours or 1–2 days max
Pull request & review
Single focused change
CI checks
Build, tests, security
Merge to trunk
Delete branch after merge
Deploy
Trunk is always releasable
Most teams release directly from trunk: when main is green and features are ready, they tag a commit (for example, v1.2.3) and deploy that tag.
When scheduled releases or long‑running hardening is needed, you can cut a temporary release branch from trunk (release/v1.2.3), stabilize it, tag the release, and delete the branch after shipping.
Older supported versions sometimes get their own short‑lived support branches (support/v1.x) so you can patch critical bugs while still merging the same fix back into trunk.
Cut release branch
branch from trunk
Harden & stabilize
only critical fixes
Tag release
v1.2.3
Delete branch
fix forward on trunk
TBD works well with semantic versioning: MAJOR.MINOR.PATCH (for example v2.1.0). Because trunk is always releasable, cutting a new version is just tagging a commit and deploying it.
Teams that release many times per day often tag automatically from CI (v1.0.1, v1.0.2, and so on) or use date‑based versions. The key is that trunk represents the latest releasable state.
Regardless of versioning style, the golden rule is that trunk builds, tests, and deploys cleanly. Any regression is fixed or reverted immediately before more work lands.
Fix forward (preferred): When a production bug is found, create a hotfix branch from trunk, fix it, merge back to trunk, tag a new patch release (for example v1.0.1), and deploy.
Support branch: If you must patch an older version (for example customers are still on v1.0.0 and trunk is at v2.0.0), branch from the old tag (support/v1.0), fix and release v1.0.1, and also port the fix back to trunk.
Revert and refix: For severe outages, immediately revert the bad change on trunk to restore stability, then investigate and re‑implement a safer fix later.
Hotfix strategies in trunk‑based development
Approach 1: Fix forward (recommended)
Approach 2: Support branch (old version)
Approach 3: Revert and refix (emergency)
In all cases, the goal is to get trunk back to a healthy, releasable state as quickly as possible.
Trunk-based development prefers small, frequent pull requests over large, infrequent merges. A typical PR is one focused change (100–200 lines) plus tests.
Each PR must pass automated checks (build, tests, lint, security scans) before it can merge to trunk. Reviews focus on correctness, clarity, and impact on reliability.
After merge, branches are deleted and CI/CD takes over, promoting changes through environments. This tight loop keeps trunk stable and deployable at all times.
Small PRs
Aim for 100–200 lines of focused change per PR.
Fast reviews
Keep review time under 30 minutes so PRs do not pile up.
Checks required
CI must be green and tests updated before merging to trunk.
Because work lands in trunk before it is fully complete, teams rely on feature flags to hide incomplete features and control rollout safely.
Flags let you deploy code with the new path turned off, enable it for internal users or a small percentage of traffic, and then gradually roll it out. If problems appear, you simply turn the flag off instead of reverting code.
Once a feature is stable, you remove the flag and any dead code paths. Keeping the flag lifecycle short avoids configuration sprawl and keeps trunk clean.
Example: React feature flag for a new flow
function CheckoutPage() {
const { featureFlags } = useFeatureFlags();
if (featureFlags.newCheckoutFlow) {
return <NewCheckout />;
}
// Safe, battle-tested behaviour
return <LegacyCheckout />;
}CI still runs on every change, but flags let you ship incomplete code to production **without exposing it to all users**.
Feature flags: deploy code, control exposure
Flag OFF (default / safe)
if (featureFlags.newPaymentFlow) {
return <NewPaymentUI />;
}
return <OldPaymentUI />;New code is deployed but hidden. All users stay on the stable path.
Gradual rollout (internal, % of users, or per‑segment)
const enableNewFlow = user.isInternal || user.country === "US" || rolloutPercentage < 10;
You can turn the feature off instantly without reverting code if metrics look bad.
Some refactors are too large to land in a single small PR. Instead of a long‑lived branch, TBD teams use branch by abstraction inside trunk.
You introduce an abstraction layer (for example, DatabaseClient) that can call either the old or new implementation. Existing code is migrated to the abstraction in small steps.
Once all callers use the abstraction and the new implementation is stable, you switch the abstraction over and delete the old code path—without ever creating a long‑running feature branch.
Example: database abstraction for a multi-step refactor
// Step 1: introduce abstraction (still calls old client)
class DatabaseClient {
async getUser(id: string) {
return legacyDb.getUserById(id);
}
}
// Step 2: gradually migrate call sites to use DatabaseClient
// ...
// Step 3: switch implementation behind the abstraction
class DatabaseClient {
async getUser(id: string) {
return prisma.user.findUnique({ where: { id } });
}
}Each step can land as a small PR to trunk—no long‑running feature branch required.
Branch by abstraction: large refactors without long‑lived branches
Phase 1: Introduce abstraction
Before
Old implementation used directly across the codebase
After
Add DatabaseClient abstraction that calls the old implementation
Phase 2: Migrate callers
Before
Call sites gradually switch to DatabaseClient
After
Both old and new implementation exist behind the abstraction
Phase 3: Flip & remove
Before
Abstraction now calls the new implementation only
After
Delete old code path once metrics are healthy
All of this happens on trunk: you land many small, safe PRs instead of one risky, long‑running feature branch.
TBD assumes that every change to trunk runs through a reliable CI pipeline: build, tests, linting, security checks, and static analysis as needed.
Teams treat a red build on trunk as a stop‑the‑line event. The first priority is to fix or revert the offending change so that main becomes green and deployable again.
After CI passes, a CD pipeline can automatically promote changes to staging and then production, or require a lightweight human approval step depending on risk tolerance.
Guard trunk with a required CI pipeline
# Example: GitHub branch protection for main/trunk - Require status checks to pass before merging - Required checks: - ci/build - ci/test - ci/lint - Require PR reviews: 1+ - Disallow direct pushes to main
These settings turn your CI into a gate: if it's not green, code cannot land on trunk.
Quick check · Trunk-based development
Question 1 of 4
Build
Compile code, install deps, create artifacts
Must pass before next stage
Test
Unit, integration, lint, security scans
Must pass before next stage
Package
Push images/packages to registries
Must pass before next stage
Deploy
Promote to staging & production
Green pipeline ⇒ safe to deploy from trunk
Large organizations such as Google famously practice trunk‑based development at scale, with tens of thousands of engineers committing to a single mainline in a monorepo.
Companies like Facebook and Netflix also rely on TBD ideas: frequent integration, heavy use of feature flags, and strong automation for testing and rollout.
Smaller teams benefit from the same principles—fast feedback and low merge complexity—without needing the full tooling stack of big tech, as long as they invest in good tests and CI.
Before adopting TBD fully, check a few readiness signals: good automated test coverage, a CI pipeline that runs quickly, and a culture that values fixing broken builds immediately.
You should be comfortable deploying to production at least once per day, have basic monitoring/alerting in place, and be willing to work with feature flags for partially complete features.
If those foundations are missing, start by strengthening CI/CD and testing, then gradually shorten branch lifetimes and move releases closer to trunk until TBD feels natural.
TBD questions often test whether you understand the trade-offs vs Git Flow and the prerequisites for TBD to work. Be ready to explain feature flags as the enabler of TBD for incomplete work. Know 'branch by abstraction' for large refactors — it is a common interview question at companies like Google and Netflix. Have a strong answer for 'how do you handle a broken build in TBD?' (stop-the-line, fix or revert in 10 minutes). The DORA data point that speed and stability improve together (not trade off) is a powerful answer to 'isn't trunk-based riskier?'
Quick check · Trunk-based development
1 / 4
Key takeaways
💡 Analogy
Trunk-based development is like a high-frequency trading floor vs a monthly batch settlement. In monthly settlement (Git Flow), traders collect transactions all month, then reconcile everything at once — the settlement day is chaotic, conflicts are discovered late, and mistakes are expensive to unwind. In continuous settlement (TBD), every transaction is settled the same day — conflicts are tiny, discovered immediately, and trivially resolved. The key insight: the cost of integration grows super-linearly with time between integrations. Halving branch lifetime cuts merge complexity by 75%, not 50%.
⚡ Core Idea
Trunk-based development is not just a branching strategy — it is a forcing function for good engineering practices. You cannot do TBD safely without: fast automated tests, feature flags for incomplete work, a culture of fixing broken builds immediately, and small-batch thinking. These practices make the team better independent of TBD. TBD is the accelerant that makes their value compound.
🎯 Why It Matters
DORA research shows that trunk-based development is one of the top technical predictors of elite software delivery performance. Teams practicing TBD deploy more frequently, have lower change failure rates, and recover from incidents faster. The causality runs both ways: TBD forces practices (small commits, fast CI, feature flags) that independently improve reliability. Teams that ship daily have fewer big-bang releases with unpredictable blast radius.
Related concepts
Explore topics that connect to this one.
Ready to see how this works in the cloud?
Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.
View role-based pathsSign in to track your progress and mark lessons complete.
Questions? Discuss in the community or start a thread below.
Join DiscordSign in to start or join a thread.