Wat is trunk based development? Een operationele gids
Samenvatting
Trunk based development is een branchingmodel waarbij alle ontwikkelaars kleine wijzigingen minstens één keer per dag integreren in één gedeelde branch. Die branch blijft altijd releasebaar. Volgens DORA betekent dat maximaal drie actieve branches, geen code freezes en een build die in minuten klaar is. Het model werkt pas als je onaf werk met feature flags verbergt en als je regressies binnen minuten ziet na elke merge.
Het is 03:00 en de releasebranch wil niet mergen. Veertig commits, drie weken oud, die dezelfde bestanden raken als main. Die pijn is precies waarom trunk based development bestaat. Wat is trunk based development dan, concreet? Het is een branchingmodel waarbij iedereen kleine wijzigingen samenvoegt in één gedeelde branch, de trunk of main, minstens één keer per dag, en die branch altijd klaar houdt om uit te rollen.
Deze gids is bedoeld voor platform engineers die Git al kennen. Hij beschrijft wat het model eist, waartegen het je beschermt en waar het stilletjes breekt.
Wat is trunk based development, operationeel gezien?
Haal de definitie terug tot de beperkingen. Alle ontwikkelaars integreren in één branch. Elke andere branch leeft uren, niet weken. De trunk bouwt en slaagt voor de tests bij elke commit, zodat hij op verzoek kan worden uitgerold.
De capabilitypagina van DORA geeft er cijfers aan: drie of minder actieve branches in de repository, merges naar de trunk minstens één keer per dag, geen code freezes en een build- en testcyclus die in enkele minuten draait. Die cijfers zijn het punt. Het model is een budget voor de feedbacklus, geen voorkeur voor een branchingstijl.

Kleine teams committen soms rechtstreeks naar de trunk. Grotere teams gebruiken kortlevende branches en pull requests voor review en buildchecks, maar nooit om werk tegen te houden van integratie. De referentiesite trunkbaseddevelopment.com beschrijft beide varianten en verwijst naar Google, dat ongeveer 35.000 ontwikkelaars op één trunk laat werken in een monorepo.
Waarom branches die lang leven op een voorspelbaar moment breken
Een featurebranch is een lening. De rente is merge-conflict, en die stapelt zich op bij elke commit die op main landt terwijl jij weg bent. Hoe langer de branch leeft, hoe groter de diff, en hoe groter de diff, hoe minder iemand hem zorgvuldig leest.
Dat vertaalt zich rechtstreeks in je change failure rate. Een merge van 2.000 regels krijgt een blik en een goedkeuring. Een merge van 60 regels wordt echt gelezen. Reviewers zijn niet lui, ze rationeren hun aandacht. Kleine batches zijn het enige mechanisme dat de kwaliteit van de review schaalbaar houdt.
De tweede kost is onzichtbaar tot de release. Twee branches die elk CI doorstaan, kunnen elkaar nog steeds breken zodra ze samenkomen. Dat merk je op het moment van integratie, het slechtst denkbare moment, met een deadline eraan vast.
Overstappen naar de trunk zonder de ondersteunende praktijken is de manier waarop teams binnen een kwartaal weer terugvallen op featurebranches. Vier dingen moeten er eerst zijn.
Een build en test die onder ongeveer tien minuten blijft. Duurt CI veertig minuten, dan gaan ontwikkelaars wijzigingen bundelen, en bundelen ondermijnt het model.
Tests die falen om echte redenen. Een flaky suite leert mensen om opnieuw te draaien en toch te mergen.
Een snel en eerlijk reviewproces. DORA noemt zware en asynchrone code review een veelvoorkomende hindernis, omdat die ontwikkelaars ertoe aanzet werk te bundelen.
Een veilige manier om onaf werk uit te rollen. Dat is de volgende sectie.
Sla je één van deze over, dan wordt de trunk de plek waar breuk zich opstapelt in plaats van de plek waar ze wordt gevangen.
Hoe merge je onaf werk zonder het uit te rollen?
Dit is de vraag die elke scepticus stelt, en het antwoord is saai: je ontkoppelt deploy van release. Code gaat dark naar productie. Een flag bepaalt wie hem ziet.
// checkout.ts
import { flags } from "./flags";
export async function renderCheckout(user: User) {
if (await flags.isEnabled("new-payment-flow", { userId: user.id })) {
return renderNewPaymentFlow(user); // gemerged naar trunk, standaard uit
}
return renderLegacyCheckout(user);
}De nieuwe flow wordt op dag één gemerged, achter een flag die uit staat. Je zet hem aan voor interne gebruikers, dan voor 1 procent, dan voor 10, met een SLO-gate bij elke stap. Als het foutpercentage het budget overschrijdt, gaat de flag uit en is de wijziging feitelijk teruggedraaid zonder deploy. Teams die gehoste flagdiensten evalueren beginnen vaak met LaunchDarkly, maar het patroon werkt met elke aanbieder of met een eigen configuratieopslag.
De tweede techniek is branch by abstraction, voor grote refactors. Je introduceert een interface, leidt de aanroepers erdoorheen, bouwt de nieuwe implementatie erachter en wisselt om zodra hij klaar is. Geen lange branch, geen big-bang merge.

De eerlijke prijs: feature flags zijn schuld met een halfwaardetijd
Niemand op het conferentiecircuit wil hier over praten. Elke flag die je toevoegt is een conditie in productie die iemand moet verwijderen. We hebben teams van 80 ingenieurs gezien die enkele honderden verouderde flags meedroegen, elk een tak in de code die niemand volledig kan testen.
Behandel flags als kortlevend, contractueel vastgelegd. Geef elke flag bij het aanmaken een eigenaar en een vervaldatum. Waarschuw bij flags die ouder zijn dan hun vervaldatum. Verwijder het dode codepad in dezelfde pull request die de flag weghaalt.
Het combinatorische risico is ook echt. Tien onafhankelijke booleaanse flags geven je 1.024 mogelijke configuraties, en je test ze nooit allemaal. Houd het aantal flaginteracties laag en houd releaseflags gescheiden van langlevende operationele schakelaars zoals kill switches.
Releasestrategieën bovenop de trunk
Er zijn twee gangbare manieren om vanaf de trunk een release te snijden, en geen van beide vereist een lange branch.
Release rechtstreeks van de trunk. Elke groene commit is een kandidaat. Bugs worden vooruit gerepareerd, met een nieuwe commit, niet door een oude branch te patchen. Dit past bij teams met sterke geautomatiseerde tests en snelle deploys.
Snijd just in time een releasebranch. Je branchet af van een bekende goede trunkcommit, verhardt die, levert uit en verwijdert hem daarna. Fixes landen eerst op de trunk en worden teruggepikt. Dit past bij teams met tragere releasepoorten of gereguleerde goedkeuring.
Welke je kiest hangt af van je detectietijd. Als je een slechte deploy binnen vijf minuten opmerkt en in twee minuten terugdraait, repareer je vooruit. Als je mean time to detect een uur is, koopt een releasebranch je een plek om te staan.

Observability is de andere helft van de deal
Trunk based development verhoogt je deployfrequentie, en daarmee het aantal momenten waarop iets mis kan gaan. Het model werkt alleen als je een regressie binnen minuten na een merge ziet. Dat betekent foutpercentages, latentiepercentielen en saturatie gekoppeld aan één specifieke release, niet aan een dashboard dat iemand op maandag bekijkt.
Een bruikbare toets: kun je na een merge zonder vijf tabbladen te openen beantwoorden of deze wijziging de p99 of het foutpercentage heeft verschoven? Zo niet, dan ben je nog niet klaar om tien keer per dag te mergen.
Welke stack je ook draait, de eis is dezelfde. Deploymarkers op je grafieken, SLO burn-rate alerts en een terugdraaipad dat een moe mens om 03:00 kan uitvoeren zonder na te denken.
Trunk based development versus GitFlow en GitHub Flow
Deze drie worden vaak door elkaar gehaald, dus scheid ze op één eigenschap: hoe lang werk van de gedeelde branch blijft.
GitFlow houdt een develop-branch, featurebranches, releasebranches en hotfixbranches aan. Werk kan weken geïsoleerd blijven. Het is ontworpen voor versioned, geplande releases, en dat voel je zodra je tien keer per dag wilt deployen.
GitHub Flow ligt dicht bij de trunk. Kortlevende branches, pull requests, merge naar main, deployen. Het verschil dat de referentiesite maakt, gaat vooral over waar de releases vandaan komen.
Trunk based development is het strengst van de drie over de levensduur van branches, en gaat uit van feature flags of branch by abstraction voor alles wat niet in één kleine wijziging kan worden uitgerold.
Als je team al GitHub Flow draait met branches die korter dan twee dagen leven, zit je dichter bij de trunk dan je denkt. De kloof zit meestal in flagdiscipline en reviewlatentie, niet in tooling.
Wanneer trunk based development de verkeerde keuze is
Sla het over, of stel het uit, in een paar gevallen. Wees eerlijk over in welk geval je zit.
Je testsuite duurt een uur en je kunt hem niet parallelliseren. Dan ga je bundelen, en bundelen breekt het model.
Je levert versioned artefacten aan klanten die jaren op oude versies blijven. Je hebt onderhoudsbranches nodig. Dat is legitiem, en je kunt nog steeds dagelijks op de trunk integreren.
Je hebt geen flagsysteem en geen zin om er een te bouwen. Half afgemaakt werk lekt dan in de releases.
Je team vertrouwt de build niet. Repareer eerst de tests. De trunk doet dat niet voor je.
Trunk based development garandeert ook niets. De bevinding van DORA is een correlatie uit hun data van 2016 en 2017, waarin teams die deze praktijken volgen betere delivery- en operationele prestaties laten zien. Er staat niet dat het hernoemen van je branches je pipeline repareert.
Begin niet met het aankondigen van een beleid. Meet eerst, en krimp daarna. Noteer je huidige levensduur van branches en de mediane grootte van je pull requests als uitgangspunt. Zet een limiet, bijvoorbeeld geen branch ouder dan twee dagen, zichtbaar op een dashboard. Repareer het traagste deel van CI. Introduceer één flag voor één echte feature, ship hem dark en ruim hem op binnen een sprint. Schaf codefreezes als laatste af, zodra je terugdraaipad in de praktijk is getest.
Wat zegt je post-mortem over je branchingmodel? Dat is de nuttige vraag voordat je uitrolt. Als je laatste incident te herleiden was tot een merge die niemand kon reviewen, een branch die drie weken uiteenliep of een release met veertig wijzigingen, dan weet je al waar de lening vervalt. Kijk naar je laatste drie storingen. Hoeveel daarvan hadden een grote, late integratie als oorzaak? Dat aantal is je businesscase.