Engineering Practice
Trunk-based: run one full cycle
Reading about trunk-based development is not the same as living one full cycle of it. Take a small service through the whole loop — integrate unfinished work daily behind a flag, do a migration too big to ship in a day without a long-lived branch, keep trunk green under a blocking gate, ramp the feature with a kill switch, and close the loop by deleting the flag — with evidence at every step.
Turn the unit’s mental model into a reproducible workflow: prove you can ship incomplete work to a releasable trunk dark, swap a component via branch by abstraction, gate every merge on a fast green build, release as a measured ramp, and clean up the scaffolding so branch debt never reappears as flag debt.
Take a small service (your own or a starter) with a real feature to add and a component to swap, and drive it through one complete trunk-based cycle — daily integration behind flags, a branch-by-abstraction migration, a fast blocking CI gate, a metric-guarded ramp with a kill switch, and flag cleanup — proving each step with the repo history, the gate config, and before/after evidence.
- The git history shows short-lived branches (each merged or deleted within a day, three or fewer active) and the unfinished feature integrating to trunk across multiple daily commits while behind an off flag — never a multi-day feature branch.
- The branch-by-abstraction migration is visible as a sequence of small green commits on trunk: interface introduced, new implementation built dark, abstraction flipped, old path and abstraction deleted — with trunk releasable at every commit.
- The CI gate config is included and demonstrably blocking: a deliberately failing PR is shown rejected at the gate, and the fast checks complete in minutes while the slow suite runs off the critical path.
- A short ramp log shows the flag exposure stages with error-rate/latency observations, plus a demonstrated kill-switch flip that returns traffic to the old path without a deploy.
- A flag-debt check: the release flag and dead old path are deleted at the end, and a one-paragraph write-up names which trunk-based mechanism each step used and why a long-lived branch was never needed.
- Add a merge queue (real or simulated) and construct two PRs that are each green against the current trunk but break when combined; show the queue catching it by testing against the projected trunk, and show a batch failure being bisected to eject the culprit.
- Add flag-lifecycle automation: track flag age like branch age, and make CI warn or fail when a release flag outlives its declared expiry, with an owner attached to every release flag.
- Wire metric guardrails into the ramp so the rollout auto-halts (or auto-rolls-back) when error rate or latency crosses a threshold — turning the release into a closed feedback loop rather than a one-way push.
- Write a one-page workflow runbook: the daily-integration rule, the flag taxonomy (release/ops/experiment/permission) with deletion policy, the branch-by-abstraction recipe, the gate-speed budget, and the rollout-and-cleanup checklist.
This is the loop you will run on every real trunk-based team: integrate small and often so drift never accumulates, ship unfinished work to a releasable trunk dark behind a flag, handle anything too big to ship in a day with branch by abstraction instead of a long-lived branch, keep the shared trunk green with a fast blocking gate (and a merge queue at scale), release as a measured ramp with a kill switch, and close every rollout by deleting the flag and the dead path so branch debt never reappears as flag debt. Doing it once on a small service makes the production discipline muscle memory.