[{"data":1,"prerenderedAt":3189},["ShallowReactive",2],{"posts-all-tags":3},[4,895,1510,1881],{"id":5,"title":6,"author":7,"body":8,"date":878,"description":879,"draft":880,"extension":881,"lastUpdated":878,"lastmod":878,"meta":882,"navigation":883,"path":884,"seo":885,"stem":886,"tags":887,"__hash__":894},"posts\u002Fbranching-release-deployment-alignment\u002Findex.md","Branching, Release, Deployment: Why All Three Must Align","Terry Pan - Principal Engineer - Stratern Solutions",{"type":9,"value":10,"toc":844},"minimark",[11,15,19,22,25,50,53,58,61,68,71,74,77,93,95,99,104,107,110,118,120,124,127,149,152,159,161,165,186,189,196,198,202,205,211,217,220,222,226,229,234,237,243,249,255,264,271,276,280,283,286,292,297,303,308,314,319,323,340,344,347,353,358,361,363,367,370,374,381,388,392,415,424,427,433,438,447,450,452,456,459,462,597,600,604,607,612,626,630,654,658,672,676,679,699,701,705,708,711,714,717,719,723,727,730,734,745,749,759,763,772,776,791,795,798,800,804,839],[12,13,6],"h1",{"id":14},"branching-release-deployment-why-all-three-must-align",[16,17,18],"p",{},"A feature ships three weeks after the code merges. A rollback takes four hours because nobody can name which of the seventeen changes broke production. A \"simple deploy\" turns into a five-person meeting on a Thursday. These aren't unrelated problems. They're symptoms of treating \"ship it\" as one decision when it's actually three: how code converges (branching), how it reaches an environment (deployment), and how users see it (release).",[16,20,21],{},"Every team has a branching strategy. Every team has a release strategy. Every team has a deployment strategy. Most engineering posts pick a side inside one of them — Gitflow vs trunk-based, blue-green vs canary, SemVer vs rolling. The side you picked matters less than where it came from.",[16,23,24],{},"Underneath every stack sits a small set of constraints, some real (customer upgrade models, regulatory windows), some manufactured (calendars adopted by habit, capability gaps nobody fixed), and those constraints are the core problem. Misalignment between the three strategies doesn't create them. It amplifies their cost and masks where they live. Coherence across the three beats modernity in any one of them, because coherent strategies are the ones derived from constraints that are real.",[26,27,28,34],"blockquote",{},[16,29,30],{},[31,32,33],"strong",{},"TL;DR",[35,36,37,41,44,47],"ul",{},[38,39,40],"li",{},"Branching, release, and deployment are three independent tracks — and underneath them sits the core problem: your constraints, some real (customer upgrade models, regulatory windows), some manufactured (copied calendars, capability gaps nobody fixed)",[38,42,43],{},"Misalignment between the tracks doesn't create those problems — it masks them (Gitflow hiding a slow CI pipeline) and amplifies them (a monthly window coupled to deployment turning one real constraint into three weeks of idle code)",[38,45,46],{},"Deployment puts code in an environment. Release exposes it to users. The two can and should be decoupled — deploy without releasing (dark launch behind a flag), release without deploying (flip a flag on code already in production)",[38,48,49],{},"Coherence across the three beats modernity in any one of them — derive each strategy from a named real constraint, strip the copied ones, then fix the capability gap that remains",[51,52],"hr",{},[54,55,57],"h2",{"id":56},"why-people-confuse-these-three-things","Why People Confuse These Three Things",[16,59,60],{},"For most of software history, all three happened in the same event. You cut a release branch, packaged a versioned build, and shipped it to a customer's server overnight. Branch, release, and deployment were synonyms because they had to be. One ceremony, one calendar entry, one rollback plan.",[16,62,63,64,67],{},"Continuous delivery broke that. Once deployment automation made it easy to push code many times a day, the three timelines decoupled. Branching became a near-continuous flow. Deployments became routine. ",[31,65,66],{},"Releases became a separate product decision about visibility and exposure."," But many teams still use the same word for all three, and the cadences quietly drift apart.",[16,69,70],{},"The misalignments that result rarely point at one specific strategy. They're coherence problems where the three don't agree on cadence, scope, or who decides what ships. The right strategies for an embedded firmware image look nothing like the right strategies for a SaaS web app. The question isn't whether each individual strategy matches current best practice; it's whether your three fit together and match what you actually ship and to whom.",[16,72,73],{},"The right mental model is three independent tracks. Branching controls integration cadence. Release controls user exposure. Deployment controls environment risk. The slowest track sets the cadence the team actually feels. Fast integration feeding a slow deploy pipeline piles up merged code nobody is testing in real conditions. A rolling release forced onto an application that can't absorb it breaks the application — online multiplayer games need every player on a synchronized version, or matchmaking fails. Speeding up one track without addressing the slower ones moves the bottleneck. It doesn't remove it.",[16,75,76],{},"And the strategy layer doesn't just move work around — it filters the signals. A loose branching model absorbs a slow CI pipeline into quarterly integration pain nobody attributes correctly; a coupled deploy-and-release calendar turns one team's real marketing window into everyone's idle month. The constraint is the disease. The strategies decide whether you feel the symptoms.",[26,78,79],{},[16,80,81,84,85,92],{},[31,82,83],{},"A note on AI in this post."," ",[86,87,91],"a",{"href":88,"rel":89},"https:\u002F\u002Fdora.dev\u002Finsights\u002Fbalancing-ai-tensions\u002F",[90],"nofollow","DORA's 2025 research"," describes generative AI as an amplifier rather than a new mechanic. Adoption correlates with both higher delivery throughput and higher delivery instability. The branching, release, and deployment models themselves don't change; what changes is the rate at which a misalignment between them turns into failure. AI's effect on DevOps practice deserves its own treatment, and this post is not it. This one stays on the three tracks and how they fit together.",[51,94],{},[54,96,98],{"id":97},"what-is-a-branching-strategy","What Is a Branching Strategy?",[26,100,101],{},[16,102,103],{},"Throughout this section, \"main\" refers to your repository's trunk branch — the primary integration line, regardless of its actual name.",[16,105,106],{},"A branching strategy is the system your team uses to introduce, track, and collaborate on code changes. It defines how individual developer changes influence the shared codebase, how those changes are integrated into the repository, and what history the team can read after the fact. The four mainstream options are trunk-based development (TBD), GitHub Flow, GitLab Flow, and Gitflow. Each makes different trade-offs about workflow shape, collaboration model, and integration cadence. The mechanics of each are the topic of the linked deep-dive.",[16,108,109],{},"The branching choice cascades into the release and deployment strategies the team can run. Short-lived branch models almost certainly need feature flags to manage incomplete features in main. Long-lived branch models need a defined integration ceremony and a way to handle hotfixes against multiple supported release lines. The strategy isn't just about Git; it sets the boundaries of what release and deployment models are even available downstream.",[26,111,112],{},[16,113,114,117],{},[31,115,116],{},"Related:"," Full deep-dive on Git branching strategies — trunk-based, GitHub Flow, GitLab Flow, and Gitflow, with the trade-offs each model makes — coming soon. Link will appear here.",[51,119],{},[54,121,123],{"id":122},"what-is-a-release-strategy","What Is a Release Strategy?",[16,125,126],{},"A release strategy is how, when, and to whom you expose new functionality. \"Release\" is a product decision dressed up in engineering language. It covers versioning (the promise the number carries), packaging (what rolls back atomically), and consumption (all at once or progressively).",[16,128,129,130,133,134,137,138,143,144,148],{},"The release strategy you can run is bounded by your packaging model. A SaaS product on a ",[31,131,132],{},"rolling release"," treats every merge as a potential release, gated by flags and rollout percentages. A ",[31,135,136],{},"versioned product"," under SemVer (a CLI, a Kubernetes operator, an embedded firmware image) ships discrete artifacts with changelogs and LTS windows. ",[86,139,142],{"href":140,"rel":141},"https:\u002F\u002Fmicrosoft.github.io\u002Fcode-with-engineering-playbook\u002FCI-CD\u002Fcontinuous-delivery\u002F",[90],"Microsoft's Engineering Playbook"," makes the distinction cleanly: continuous delivery means the artifact is ",[145,146,147],"em",{},"always shippable",", not that every artifact ships.",[16,150,151],{},"The most under-discussed part of release strategy is consumption coupling. If your customers pin to specific versions, your release cadence is constrained by their upgrade tolerance, not your engineering velocity. No amount of internal decoupling changes that ceiling.",[26,153,154],{},[16,155,156,158],{},[31,157,116],{}," Detailed guide on release strategy patterns and versioning trade-offs coming soon. Link will appear here.",[51,160],{},[54,162,164],{"id":163},"what-is-a-deployment-strategy","What Is a Deployment Strategy?",[16,166,167,168,171,172,175,176,179,180,185],{},"A deployment strategy is the technical mechanism that gets new code running in an environment (every environment, not just production). It breaks down into three independent choices. ",[31,169,170],{},"Progression"," is which environments code passes through and the gates at each hop. ",[31,173,174],{},"Delivery mechanism"," is push pipelines vs pull-based GitOps, immutable artifacts vs in-place updates. ",[31,177,178],{},"Cutover"," is how new code replaces old once it arrives: blue-green, canary, rolling update, recreate, with adjacent variants like shadow, ring, and A\u002FB (see ",[86,181,184],{"href":182,"rel":183},"https:\u002F\u002Fdeveloper.hashicorp.com\u002Fwell-architected-framework\u002Fdefine-and-automate-processes\u002Fdeploy\u002Fzero-downtime-deployments",[90],"HashiCorp's Zero-Downtime Deployments guide",").",[16,187,188],{},"What you can actually run on each axis depends on your infrastructure and your release model. Blue-green needs capacity headroom; canary needs traffic routing and observability; both need a rollback path you've actually rehearsed. The cutover choice is mostly an availability and rollback question, not a feature-exposure question. That's what the release strategy handles.",[26,190,191],{},[16,192,193,195],{},[31,194,116],{}," Full deep-dive on deployment strategies — progression, delivery mechanism, and cutover patterns (blue-green, canary, rolling), with the trade-offs each makes — coming soon. Link will appear here.",[51,197],{},[54,199,201],{"id":200},"deployment-without-release-release-without-deployment","Deployment Without Release. Release Without Deployment.",[16,203,204],{},"This is where most teams' mental model breaks. A deployment puts new code into a running environment. A release exposes that code to users. The two events can happen on separate timelines.",[16,206,207,210],{},[31,208,209],{},"Deployment without release."," Code merges to main on Tuesday, deploys to production behind a feature flag set to off. Zero users see it. The code is live in production, exercising the database, sitting in the same memory space as everything else, fully observable. Engineering has shipped. Product hasn't released. When marketing runs the launch on Friday, the flag flips and the feature appears. The deployment happened three days earlier and got soaked under real load. The release is a configuration change, not a code change.",[16,212,213,216],{},[31,214,215],{},"Release without deployment."," A feature has been in production for two weeks, gated to 1% of traffic for monitoring. The team raises the flag to 100%. No code shipped. No pipeline ran. Users get a new experience anyway. The release happened without a deployment.",[16,218,219],{},"Once you internalize this, the second-order benefits stack up. Rollback becomes a flag flip instead of a deploy. Risk-bearing experiments become routine rather than special. The deployment pipeline can run at the engineering team's natural cadence, not the marketing calendar's. The release process can serve customer-facing requirements without holding code hostage. Is your team treating these as one decision or two? The answer determines how much friction your DevOps practice quietly accumulates each week.",[51,221],{},[54,223,225],{"id":224},"how-does-misalignment-show-up","How Does Misalignment Show Up?",[16,227,228],{},"Misalignment is rarely loud: it's the slow tax on every release cycle that nobody assigns a name to. It's also rarely the root cause. Underneath each example below sits a constraint: a slow pipeline, a missing flag platform, a release calendar nobody re-examined. The misalignment is what that constraint looks like after the strategy layer has finished masking or amplifying it. Each of these is the team's own to fix; the genuinely external constraints come in the next section. Each example separates the real constraint from the self-imposed copy. The fix is never \"abandon the constraint\" — it's \"stop letting it cascade into tracks that didn't inherit it,\" then fix the constraint that's actually left.",[230,231,233],"h3",{"id":232},"gitflow-that-hides-a-slow-ci-pipeline","Gitflow that hides a slow CI pipeline",[16,235,236],{},"A single-version SaaS team runs Gitflow (develop, release branches, dual-merge hotfixes), a model built to manage multiple shipped versions, on a product that ships one. The ceremony taxes all three tracks.",[16,238,239,242],{},[31,240,241],{},"Release:"," features can only reach users through a release-branch cut, so release cadence is welded to branch ceremony.",[16,244,245,248],{},[31,246,247],{},"Deployment:"," five branch types onto three environments makes the mapping ambiguous: develop to staging, release to UAT, main to prod? Every environment runs a different branch, so no environment tested exactly what ships, and each deploy starts with a \"which branch goes where?\" conversation.",[16,250,251,254],{},[31,252,253],{},"CI:"," develop is nominally the trunk, but features land on it weeks apart. So CI runs often while integrating rarely. Each green feature-branch build tests one change against a stale base, and changes first meet each other in a late merge or on the release branch. That hides the pipeline in both directions. If CI\u002FCD is fast, the branching is the constraint — the speed is wasted on isolated branches. If CI\u002FCD is slow, you hardly notice. Forty-five minutes barely matters when merges are rare, so it never gets fixed. Push fifteen merges a day through it, trunk-based style, and it would be unbearable within a week.",[16,256,257,258,263],{},"Even Gitflow's author ",[86,259,262],{"href":260,"rel":261},"https:\u002F\u002Fnvie.com\u002Fposts\u002Fa-successful-git-branching-model\u002F",[90],"steers continuously delivered web apps toward simpler models",". The model isn't just slow — it's an anesthetic. I've watched a forty-five-minute pipeline survive years of complaints precisely because the Gitflow cadence kept anyone from feeling it — until the team tried to merge ten times a day and it became the whole problem inside a fortnight.",[16,265,266],{},[267,268],"img",{"alt":269,"src":270},"Gitflow branch diagram for a single-version product showing five branch types — main, hotfix, release, develop, and two feature branches — over a four-week timeline. Feature branches live for weeks before merging into develop, where the first real integration happens as large, conflict-prone merges marked with red rings. A release branch is cut from develop, receives stabilization fixes, then merges to main as the single deploy event of the cycle, tagged v1.5, with a dashed back-merge into develop. A hotfix branches from main, merges back tagged v1.4.1, and needs its own back-merge to develop. Numbered callouts mark where CI is slowed by deferred integration, where release is slowed by branch ceremony and double merges, and where deployment is slowed to one event per cycle.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fgitflow-on-a-single-version-product-the-ceremony.png",[16,272,273],{},[145,274,275],{},"Every branch type in the ceremony is doing a job Gitflow assumes you need — multi-version support, scheduled stabilization. On a single-version product none of those jobs exist, but the tax still gets paid: integration waits on feature branches, production waits on the release branch, and the slow CI underneath it all never hurts enough to get fixed.",[230,277,279],{"id":278},"trunk-based-branching-with-a-calendar-driven-monthly-release","Trunk-based branching with a calendar-driven monthly release",[16,281,282],{},"Where Gitflow masks its underlying constraint, this shape amplifies one. The branches are short, the merges are clean, and then the code sits in main for three weeks waiting for the release calendar. The buried mistake is the assumption that deployment has to match the release cadence: because users can't see the feature until the window opens, the code doesn't ship anywhere at all.",[16,284,285],{},"But the window is a release constraint: it says when users see the change, not when code is allowed to reach production. Held to the same calendar, deployment goes dark for weeks. Engineers stop feeling the connection between merging and shipping, and the feedback loop you optimized for at the Git layer is severed by a coupling the release calendar never actually demanded.",[16,287,288],{},[267,289],{"alt":290,"src":291},"Timeline of trunk-based development where the monthly window gates deployment too. Early merges are deployed and released together at a monthly gate just after week one; for the next three weeks commits keep merging to main but stay out of production and unreleased, shown as hollow dots inside a red zone, until the next monthly gate at week four deploys and releases the whole batch in one event. Both monthly releases are cut as git tags, v1.4 and v1.5.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fcoupled-the-monthly-window-gates-deployment-too.png",[16,293,294],{},[145,295,296],{},"The branching layer is fast — short branches, clean merges — but the release calendar has been copied onto deployment, so three weeks of merged work sits on main: not in production, not released, generating no feedback.",[16,298,299],{},[267,300],{"alt":301,"src":302},"Timeline of the decoupled fix. The same commits merge to main, and every merge immediately deploys to production with its feature flag off, shown as hollow squares inside a green zone: dark, invisible to users, but observable under real load. The monthly windows sit at the same points but only flip flags: the early batch is already released as filled green squares, and at the week-four window the flags flip and the dark features are released with no code change. Each window's release is still cut as a git tag: v1.4 at week one, v1.5 at week four.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fdecoupled-deploy-on-merge-release-by-flag-flip.png",[16,304,305],{},[145,306,307],{},"Same commits, same monthly windows. Every merge deploys to production immediately with its flag off — dark, invisible to users, but soaking under real load. The window stops being a deploy event: when it opens, the flags flip and the features are released without a code change.",[16,309,310],{},[267,311],{"alt":312,"src":313},"Timeline of the fully continuous option. The same commits merge to main, and every merge immediately deploys to production and releases to users, shown as filled green squares on the prod lane at every commit. There are no monthly windows; release cadence equals merge cadence, and every merge is cut as its own git tag, shown as small tag markers above each commit.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fcontinuous-deploy-and-release-on-every-merge.png",[16,315,316],{},[145,317,318],{},"And if the monthly window turns out to be convention rather than a real constraint, the third option is to drop it: every merge deploys and releases as it lands. Flags still gate incomplete work inside each merge — which is exactly what the continuous-deployment failure below is missing.",[230,320,322],{"id":321},"but-deployments-cause-errors-and-downtime-too","\"But deployments cause errors and downtime too\"",[16,324,325,326,329,330,335,336,339],{},"It's the strongest objection to everything above, and the one I hear most when I suggest deploying more often. The fear is rational: for a team that deploys monthly, every deployment it has ever run genuinely was dangerous, because each one carried a month of changes. But that risk is a property of batch size, not of deployment as an activity. The calendar doesn't reduce it — it concentrates it into one compound event where any failure has forty possible causes (the four-hour rollback from the top of this post). A decade of DORA research finds throughput and stability are not a trade-off: frequent deployers have ",[145,327,328],{},"lower"," change failure rates and recover faster (",[86,331,334],{"href":332,"rel":333},"https:\u002F\u002Fdora.dev\u002Fguides\u002Fdora-metrics\u002F",[90],"DORA's software delivery metrics","). The mechanism, the fear loop that keeps reluctant teams stuck, and the on-ramp that never requires more user-facing risk than a team takes today are covered in the deployment strategies deep-dive ",[145,337,338],{},"(coming soon)",".",[230,341,343],{"id":342},"continuous-deployment-with-no-feature-flag-platform","Continuous deployment with no feature flag platform",[16,345,346],{},"Every merge ships to all users immediately. Half-finished features can't merge, so they fester in long-lived branches, and the team quietly slides back toward Gitflow. The branching and deployment strategies look modern; the release model forces the branching strategy backward.",[16,348,349],{},[267,350],{"alt":351,"src":352},"Diagram of a team running continuous deployment without feature flags. Production sits at the top: with no flags, every merge to main is deployed and released to all users in one event, shown as orange diamonds. Because nothing half-finished can merge, three feature branches live below main for one to three weeks, and main receives only three giant merges in four weeks, each marked with a red conflict ring. Each release then crawls through CI and CD, slowed by the weeks of accumulated changes it carries. A causal chain at the bottom summarizes the direction of blame: no flag platform leads to long-lived branches, which lead to giant merges and conflicts, which make CI and CD slow and risky — the slowness is the symptom, not the cause.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fcontinuous-deployment-no-flags-trunk-based-in-na.png",[16,354,355],{},[145,356,357],{},"Read the chain from the root: with no flag to separate exposure from deployment, completeness becomes a merge precondition, branches run long, and the merges that finally land are giant. The slow, risky CI\u002FCD is the symptom at the end of that chain, not the cause — each run carries weeks of changes and the conflict fallout that comes with them. Add a flag platform and the chain unwinds from the front.",[16,359,360],{},"The realignment is a flag platform: incomplete work merges and deploys dark, and exposing a feature becomes a per-feature release decision instead of a side effect of deploying.",[51,362],{},[54,364,366],{"id":365},"what-happens-when-the-constraint-is-real","What Happens When the Constraint Is Real?",[16,368,369],{},"The misalignments so far were couplings to strip out: remove the copy and the constraint underneath sits quietly. The constraints here are heavier. They come from outside the engineering organisation (a regulator's release window, a contract promising customers fixes on the version they pinned), and the organisation has to adhere to them whether it likes them or not. They can't be designed away. They can only be mishandled: by letting them cascade into tracks they never bound, or by paying their cost without the policy that keeps the bill finite. The first example below caps how often you ship but not how fast you can work; most of the stack it seems to bind, it doesn't. The second genuinely dictates structure, and stays affordable only with an explicit cap.",[230,371,373],{"id":372},"a-fixed-release-window-caps-frequency-not-speed","A fixed release window caps frequency, not speed",[16,375,376,377,380],{},"A genuinely fixed release window (a regulator's quarterly approval, a customer's change calendar) caps how ",[145,378,379],{},"often"," you ship, not how fast you work behind it. Integrate continuously and deploy to dev, staging, and UAT continuously, and you validate far more features per window; only the release waits.",[16,382,383,384,387],{},"The fear that this means a bigger, riskier release is half misattribution and half real. The merge crunch comes from holding features on branches, not from speed; integrate continuously and the release just tags what's already on main. What's real is blast radius: more lands on users at once, a job for feature flags or a ring rollout, not a reason to slow down. The one thing that genuinely caps batch ",[145,385,386],{},"size"," is the customer's capacity to absorb change. And if that's why the window exists, that's the real constraint, where the next example begins.",[230,389,391],{"id":390},"a-release-branch-per-supported-version-what-the-legitimate-constraint-costs","A release branch per supported version: what the legitimate constraint costs",[16,393,394,395,399,400,403,404,399,409,414],{},"When customers pin to a version and expect fixes without a forced upgrade, every release becomes a long-lived branch (",[396,397,398],"code",{},"release\u002F1.4",", ",[396,401,402],{},"release\u002F1.5",") so a hotfix can be cut against exactly what each customer runs. This is the coherent stack for versioned products, and current guidance is consistent on the mechanics. Branch as late as possible. Never develop on the release branch. Fix bugs on main first, then cherry-pick them to each affected line: the \"upstream first\" policy (",[86,405,408],{"href":406,"rel":407},"https:\u002F\u002Ftrunkbaseddevelopment.com\u002Fbranch-for-release\u002F",[90],"trunk-based development's branch-for-release",[86,410,413],{"href":411,"rel":412},"https:\u002F\u002Fdocs.gitlab.com\u002Fuser\u002Fproject\u002Frepository\u002Fbranches\u002Fstrategies\u002F",[90],"GitLab's branching strategies","). Tag a new patch version on the branch for every backported fix.",[16,416,417,418,423],{},"The cost scales with every line you keep alive: each supported branch is a hotfix target, a backport queue, and a full regression matrix of its own. That's why mature versioned products cap the window explicitly rather than letting support accrete. ",[86,419,422],{"href":420,"rel":421},"https:\u002F\u002Fkubernetes.io\u002Freleases\u002F",[90],"Kubernetes maintains release branches for only the latest three minor versions",", roughly fourteen months each. Commercial products publish the same idea as N−2 or LTS policies.",[16,425,426],{},"The branch structure is the legitimate answer to a consumption constraint; the published support window is what keeps that answer affordable. A team running this stack without an end-of-support policy hasn't aligned with their constraint — they've signed up for unbounded maintenance.",[16,428,429],{},[267,430],{"alt":431,"src":432},"Timeline of a versioned product where every release is cut to its own release branch. Commits flow on main; at week one a release branch for version one point four is cut and tagged v1.4.0, and at week four a branch for one point five is cut and tagged v1.5.0. An older branch, release one point three, predates the chart and receives a backported hotfix tagged v1.3.8, as does release one point four with v1.4.1: fixes land on main first and are cherry-picked to each affected line. An amber zone highlights that every supported branch adds hotfix, backport, and regression-test load, and release one point three reaches end of support when v1.5 ships under a support-latest-two policy.","\u002Fposts\u002Fbranching-release-deployment-alignment\u002Fversioned-a-release-branch-per-supported-line.png",[16,434,435],{},[145,436,437],{},"Branch late, tag each release, fix on main and cherry-pick to each line. The amber zone is the point: every live branch is its own backport queue and regression matrix — affordable only with an explicit support cap.",[16,439,440,441,444,445,339],{},"The deployment strategy follows from the same constraint: the customer owns the production deploy, so progressive delivery moves ",[145,442,443],{},"before"," release instead of after. That's the alignment test passing in reverse: one real constraint cascading coherently into all three tracks. The misalignment is the team that copies SaaS assumptions (deploy-on-merge, release-by-flag) onto production it doesn't control. The mechanics (build-once promotion, pull-based channels, rollback-engineered artifacts) are in the deployment strategies deep-dive ",[145,446,338],{},[16,448,449],{},"Whether the constraint is self-inflicted or external, the recovery is one move: name it, then check whether your strategies mask it, amplify it, copy it where it doesn't belong, or pay its cost without a cap. The next section turns that into diagnostic questions.",[51,451],{},[54,453,455],{"id":454},"how-do-you-test-alignment-on-your-team","How Do You Test Alignment on Your Team?",[16,457,458],{},"The right question isn't \"which branching strategy is best.\" It's \"which constraints are real, and which did we manufacture?\" Real constraints (customer upgrade model, regulatory windows, architecture, contractual SLAs) are inputs you can't choose. The Theory of Constraints lesson for DevOps is that the slowest track sets the cadence the whole team feels, so optimizing any other track past the bottleneck just stockpiles work-in-progress nobody can ship. The expensive misalignments aren't the bottlenecks reality imposes. They're the cadences your team copied onto strategies that didn't need them — and the real bottlenecks your strategies have stopped you from feeling.",[16,460,461],{},"Every pattern above reduces to the same shape: a constraint underneath, a misalignment on top, and one move that realigns the three tracks. The table recaps them.",[463,464,466],"div",{"style":465},"overflow-x:auto;margin:24px 0;",[467,468,470,471,470,476,470,502],"table",{"style":469},"width:100%;border-collapse:collapse;font-family:'Inter Tight',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:0.9375rem;line-height:1.45;background:#fefdfb;border:1px solid #dcd6d1;border-top:none;border-radius:0 0 8px 8px;overflow:hidden;","\n  ",[472,473,475],"caption",{"style":474},"caption-side:top;text-align:left;padding:12px 16px;background:#fefdfb;border:1px solid #dcd6d1;border-bottom:none;border-radius:8px 8px 0 0;font-family:'Instrument Sans','Inter Tight',-apple-system,sans-serif;font-weight:600;color:#1a1511;font-size:1.0625rem;","Every misalignment, the real constraint beneath it, and the one move that realigns the three tracks",[477,478,479,480,470],"thead",{},"\n    ",[481,482,484,485,484,491,484,495,484,498,479],"tr",{"style":483},"background:#f2f0ec;","\n      ",[486,487,490],"th",{"scope":488,"style":489},"col","text-align:left;padding:12px 16px;background:#f2f0ec;color:#1a1511;border-bottom:1px solid #c9c3bc;","Scenario",[486,492,494],{"scope":488,"style":493},"text-align:left;padding:12px 16px;background:#f2f0ec;color:#c53637;border-bottom:1px solid #c9c3bc;","What's misaligned",[486,496,497],{"scope":488,"style":489},"Constraint underneath",[486,499,501],{"scope":488,"style":500},"text-align:left;padding:12px 16px;background:#f2f0ec;color:#2c513c;border-bottom:1px solid #c9c3bc;","Aligned move",[503,504,479,505,479,524,479,538,479,552,479,566,479,580,470],"tbody",{},[481,506,484,507,484,512,484,517,484,520,479],{},[486,508,511],{"scope":509,"style":510},"row","text-align:left;vertical-align:top;padding:12px 16px;font-weight:600;color:#1a1511;border-bottom:1px solid #ece7e1;","Gitflow on a single-version SaaS",[513,514,516],"td",{"style":515},"vertical-align:top;padding:12px 16px;color:#47413c;border-bottom:1px solid #ece7e1;","Multi-version branch ceremony welds release and deployment to a model the product doesn't need",[513,518,519],{"style":515},"A slow CI pipeline, masked by rare integration",[513,521,523],{"style":522},"vertical-align:top;padding:12px 16px;color:#2c513c;border-bottom:1px solid #ece7e1;","Drop to trunk-based, then fix the pipeline the ceremony was hiding",[481,525,484,526,484,529,484,532,484,535,479],{"style":483},[486,527,528],{"scope":509,"style":510},"Trunk-based + monthly release calendar",[513,530,531],{"style":515},"The release calendar is copied onto deployment; merged code sits dark for weeks",[513,533,534],{"style":515},"A real release window — but it only binds release",[513,536,537],{"style":522},"Deploy on merge behind flags; flip flags when the window opens",[481,539,484,540,484,543,484,546,484,549,479],{},[486,541,542],{"scope":509,"style":510},"\"Deployments cause errors too\"",[513,544,545],{"style":515},"Risk is attributed to deploy frequency instead of batch size",[513,547,548],{"style":515},"Large batch size, not deployment as an activity",[513,550,551],{"style":522},"Deploy smaller and more often; deploy dark behind flags",[481,553,484,554,484,557,484,560,484,563,479],{"style":483},[486,555,556],{"scope":509,"style":510},"Continuous deployment, no flag platform",[513,558,559],{"style":515},"The release model forces branching backward into long-lived branches",[513,561,562],{"style":515},"A missing feature-flag platform",[513,564,565],{"style":522},"Add flags so incomplete work can merge and deploy dark",[481,567,484,568,484,571,484,574,484,577,479],{},[486,569,570],{"scope":509,"style":510},"A fixed release window",[513,572,573],{"style":515},"The window is treated as a cap on how fast you can work and integrate, not just on when users see changes",[513,575,576],{"style":515},"A genuinely fixed external release cadence (regulator or customer)",[513,578,579],{"style":522},"Integrate continuously and deploy to non-prod every change; only the release waits for the window",[481,581,484,582,484,586,484,590,484,593,479],{"style":483},[486,583,585],{"scope":509,"style":584},"text-align:left;vertical-align:top;padding:12px 16px;font-weight:600;color:#1a1511;","A release branch per supported version",[513,587,589],{"style":588},"vertical-align:top;padding:12px 16px;color:#47413c;","Coherent — the risk is unbounded maintenance with no end date",[513,591,592],{"style":588},"Customers pinned to versions they upgrade themselves",[513,594,596],{"style":595},"vertical-align:top;padding:12px 16px;color:#2c513c;","Branch late, cherry-pick fixes, publish an explicit support window (N−2 or LTS)",[16,598,599],{},"Work through the questions below at your next architecture review. The constraint questions surface what's actually fixed. The alignment questions test whether the three strategies fit together.",[230,601,603],{"id":602},"constraint-questions-whats-actually-fixed","Constraint questions: what's actually fixed?",[16,605,606],{},"For each strategy, separate genuine external constraints from cadences adopted by convention.",[16,608,609],{},[31,610,611],{},"Branching:",[35,613,614,617,620,623],{},[38,615,616],{},"What's forcing your current integration cadence: tooling, audit trail, regulatory requirement, or convention?",[38,618,619],{},"Does your domain genuinely require multiple long-lived release lines, or only a support history for hotfixes?",[38,621,622],{},"Is your branching model solving a problem you actually have (multiple shipped versions, regulated audit lines), or one inherited from a product that did?",[38,624,625],{},"How long can a feature legitimately stay on a branch before the cost of merge debt outweighs the benefit of isolation?",[16,627,628],{},[31,629,241],{},[35,631,632,635,638,641,651],{},[38,633,634],{},"Who decides when users see a new feature: engineering, product, marketing, or the customer?",[38,636,637],{},"Are your customers pinned to versions they upgrade on their own schedule, or do they take whatever you ship?",[38,639,640],{},"Is your release cadence imposed by an external model (regulated firmware, on-prem installer, contractual SLA) or by internal calendar?",[38,642,643,644,646,647,650],{},"If your release window is genuinely fixed, is it capping how ",[145,645,379],{}," you ship — or have you let it cap how ",[145,648,649],{},"fast"," you work behind it? And if batch size is the limit, is that your pipeline or your customers' capacity to absorb change?",[38,652,653],{},"What's the smallest release unit your packaging model allows: one change, a tagged version, a quarterly bundle?",[16,655,656],{},[31,657,247],{},[35,659,660,663,666,669],{},[38,661,662],{},"What's the technical floor on how often you can push to a production-like environment? (Pipeline duration, infrastructure provisioning, manual approvals.)",[38,664,665],{},"Are the same gates required in non-prod environments, or only in prod?",[38,667,668],{},"Where are the manual steps, and are they manual because of audit, risk, or because nobody automated them?",[38,670,671],{},"How long does a rollback take, and does that time match your team's actual recovery appetite?",[230,673,675],{"id":674},"alignment-questions-do-the-three-agree","Alignment questions: do the three agree?",[16,677,678],{},"Once you've isolated what's actually fixed, test whether the three strategies fit together.",[35,680,681,684,687,690,693,696],{},[38,682,683],{},"How often do you deploy to production? How often do you release a new feature to users? If those numbers are identical, you've coupled the two — confirm that's a choice, not a default.",[38,685,686],{},"Which of the three strategies is currently the slowest? Is that slowness justified by an external constraint you just identified, or did the team adopt it by convention?",[38,688,689],{},"Is any other strategy running faster than the slowest can absorb? (Fast merges piling onto a slow deploy; fast deploys with no flags to gate exposure.)",[38,691,692],{},"What might your current setup be hiding? A branching model that integrates rarely can absorb a slow, flaky pipeline for months — if you had a capability gap, would your workflow force you to feel it, or quietly route around it?",[38,694,695],{},"For each pair (branching↔release, release↔deployment, branching↔deployment), is one constraining the other? Does that constraint serve the business, or just reflect inheritance from an unrelated layer?",[38,697,698],{},"If you replaced one strategy with a popular alternative (trunk-based development, continuous deployment, canary), would the other two operate at the new cadence without breaking?",[51,700],{},[54,702,704],{"id":703},"the-takeaway","The Takeaway",[16,706,707],{},"A team running Gitflow + scheduled releases + blue-green deployments because they ship versioned software to regulated customers is doing better engineering than a team running TBD + monthly releases because someone read a DORA report and only changed one track. Coherence matters more than modernity.",[16,709,710],{},"The constraint questions usually surface one strategy that's genuinely fixed: most often release, sometimes deployment, rarely branching. Everything else is a cadence the team chose. The mistake is letting the real constraint cascade into strategies that didn't inherit it: long-lived branches because the release is quarterly, manual prod deploys copied into manual non-prod deploys, blue-green infrastructure paired with a monthly release calendar. Strip the self-imposed copies out, and the bottleneck that remains is the one worth investing in.",[16,712,713],{},"That remaining bottleneck is usually a capability, not a strategy: a slow pipeline, a missing flag platform, an unrehearsed rollback. Alignment doesn't substitute for fixing it; alignment is what makes it visible and tells you it's the one that matters. The leverage I keep coming back to isn't the strategy on the whiteboard — it's the shared capability underneath it. Fix the pipeline, the flag platform, or the rollback once, and every team downstream gets faster at the same time. That's the line between a strategy debate and a scaling investment. Notice, too, that branching is almost never the strategy you change to fix a misalignment. But it's often where one is created (a model copied from products with constraints you don't have) or hidden (integration tolerances loose enough to absorb the signal).",[16,715,716],{},"The other mistake is upgrading one strategy in isolation. New pipeline, same branching model. Trunk-based merges, same hand-cranked release.",[51,718],{},[54,720,722],{"id":721},"faq","FAQ",[230,724,726],{"id":725},"whats-the-difference-between-a-release-and-a-deployment","What's the difference between a release and a deployment?",[16,728,729],{},"A deployment is the technical act of putting new code in a running environment. A release is the moment users get access to that code or feature. Feature flags are the most common mechanism: code can be deployed for weeks before the flag is flipped to release the feature.",[230,731,733],{"id":732},"can-you-do-canary-deployments-without-feature-flags","Can you do canary deployments without feature flags?",[16,735,736,737,740,741,744],{},"Yes, at the infrastructure layer. A canary deployment routes a small percentage of traffic to a new version regardless of feature flags. But canaries and feature flags solve different problems: canaries de-risk ",[145,738,739],{},"the deployment itself"," (is the new build healthy?), while flags de-risk ",[145,742,743],{},"the release"," (should users see this feature?). Most mature teams use both layered together.",[230,746,748],{"id":747},"isnt-deploying-to-production-more-often-riskier","Isn't deploying to production more often riskier?",[16,750,751,752,329,754,758],{},"No — a decade of DORA research finds the opposite: teams that deploy more frequently have ",[145,753,328],{},[86,755,757],{"href":332,"rel":756},[90],"DORA's delivery metrics","). Deployment risk scales with batch size, not deployment count. A monthly deploy concentrates every change from the month into one compound event with dozens of possible causes per failure; small frequent deploys shrink the blast radius, make diagnosis near-trivial, and keep the deployment machinery rehearsed. Deploying dark behind a feature flag removes user exposure from the deploy event entirely.",[230,760,762],{"id":761},"does-trunk-based-development-require-continuous-deployment","Does trunk-based development require continuous deployment?",[16,764,765,766,771],{},"Not strictly, but the combination is the natural fit. TBD assumes branches measured in hours and at least one daily merge (",[86,767,770],{"href":768,"rel":769},"https:\u002F\u002Fdora.dev\u002Fcapabilities\u002Ftrunk-based-development\u002F",[90],"DORA, Trunk-Based Development capability","). If main is the integration point but deployments happen monthly, you've recreated a code-freeze problem by another name. Most teams that adopt TBD seriously also move toward deploy-on-merge with feature flags managing user exposure.",[230,773,775],{"id":774},"what-is-progressive-delivery","What is progressive delivery?",[16,777,778,779,784,785,790],{},"Progressive delivery is the operational discipline of releasing changes to small user segments and expanding based on observed behavior, typically combining canary deployment with feature flags. The term was coined by ",[86,780,783],{"href":781,"rel":782},"https:\u002F\u002Fredmonk.com\u002Fjgovernor\u002F2018\u002F08\u002F06\u002Ftowards-progressive-delivery\u002F",[90],"James Governor of RedMonk in 2018"," and is now used widely across the feature-management ecosystem (",[86,786,789],{"href":787,"rel":788},"https:\u002F\u002Fwww.flagsmith.com\u002Fblog\u002Fprogressive-delivery",[90],"Flagsmith",", LaunchDarkly). It's release strategy and deployment strategy working in concert: deploy progressively to environments, release progressively to user cohorts.",[230,792,794],{"id":793},"how-do-versioned-products-clis-sdks-embedded-software-fit-this-model","How do versioned products (CLIs, SDKs, embedded software) fit this model?",[16,796,797],{},"Versioned products keep deployment, release, and branching closer together by necessity, because the artifact itself is the unit of distribution. Gitflow, semantic versioning, and customer-driven deployment form a coherent stack here. The deploy\u002Frelease decoupling that SaaS teams get from feature flags shows up in versioned products as version pinning and gradual customer upgrade cycles instead.",[51,799],{},[54,801,803],{"id":802},"sources","Sources",[35,805,806,809,812,815,818,821,824,827,830,833,836],{},[38,807,808],{},"DORA. \"Balancing the tensions of AI.\" dora.dev\u002Finsights\u002Fbalancing-ai-tensions\u002F. Accessed 13 June 2026.",[38,810,811],{},"DORA. \"DORA's software delivery metrics.\" dora.dev\u002Fguides\u002Fdora-metrics\u002F. Accessed 13 June 2026.",[38,813,814],{},"DORA. \"Trunk-based development (capability).\" dora.dev\u002Fcapabilities\u002Ftrunk-based-development\u002F. Accessed 13 June 2026.",[38,816,817],{},"Microsoft. \"Continuous Delivery: Engineering Playbook.\" microsoft.github.io\u002Fcode-with-engineering-playbook\u002F. Accessed 13 June 2026.",[38,819,820],{},"HashiCorp. \"Zero-Downtime Deployments: Well-Architected Framework.\" developer.hashicorp.com. Accessed 13 June 2026.",[38,822,823],{},"Vincent Driessen. \"A successful Git branching model.\" nvie.com. Accessed 13 June 2026, originally published 2010.",[38,825,826],{},"Trunk-Based Development. \"Branch for Release.\" trunkbaseddevelopment.com\u002Fbranch-for-release\u002F. Accessed 13 June 2026.",[38,828,829],{},"GitLab. \"Branching strategies.\" docs.gitlab.com. Accessed 13 June 2026.",[38,831,832],{},"Kubernetes. \"Releases.\" kubernetes.io\u002Freleases\u002F. Accessed 13 June 2026.",[38,834,835],{},"James Governor (RedMonk). \"Towards Progressive Delivery.\" redmonk.com. Accessed 13 June 2026, originally published 2018.",[38,837,838],{},"Flagsmith. \"Progressive Delivery.\" flagsmith.com\u002Fblog\u002Fprogressive-delivery. Accessed 13 June 2026.",[840,841,843],"script",{"type":842},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What's the difference between a release and a deployment?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"A deployment is the technical act of putting new code in a running environment. A release is the moment users get access to that code or feature. Feature flags are the most common mechanism: code can be deployed for weeks before the flag is flipped to release the feature.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can you do canary deployments without feature flags?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes, at the infrastructure layer. A canary deployment routes a small percentage of traffic to a new version regardless of feature flags. But canaries and feature flags solve different problems: canaries de-risk the deployment itself (is the new build healthy?), while flags de-risk the release (should users see this feature?). Most mature teams use both layered together.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Isn't deploying to production more often riskier?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No — a decade of DORA research finds the opposite: teams that deploy more frequently have lower change failure rates and recover faster. Deployment risk scales with batch size, not deployment count. A monthly deploy concentrates every change from the month into one compound event with dozens of possible causes per failure; small frequent deploys shrink the blast radius, make diagnosis near-trivial, and keep the deployment machinery rehearsed. Deploying dark behind a feature flag removes user exposure from the deploy event entirely.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Does trunk-based development require continuous deployment?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Not strictly, but the combination is the natural fit. TBD assumes branches measured in hours and at least one daily merge. If main is the integration point but deployments happen monthly, you've recreated a code-freeze problem by another name. Most teams that adopt TBD seriously also move toward deploy-on-merge with feature flags managing user exposure.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What is progressive delivery?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Progressive delivery is the operational discipline of releasing changes to small user segments and expanding based on observed behavior, typically combining canary deployment with feature flags. The term was coined by James Governor of RedMonk in 2018 and is now used widely across the feature-management ecosystem, including tools like Flagsmith and LaunchDarkly. It's release strategy and deployment strategy working in concert: deploy progressively to environments, release progressively to user cohorts.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How do versioned products (CLIs, SDKs, embedded software) fit this model?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Versioned products keep deployment, release, and branching closer together by necessity, because the artifact itself is the unit of distribution. Gitflow, semantic versioning, and customer-driven deployment form a coherent stack here. The deploy\u002Frelease decoupling that SaaS teams get from feature flags shows up in versioned products as version pinning and gradual customer upgrade cycles instead.\"\n      }\n    }\n  ]\n}\n",{"title":845,"searchDepth":846,"depth":846,"links":847},"",3,[848,850,851,852,853,854,860,864,868,869,877],{"id":56,"depth":849,"text":57},2,{"id":97,"depth":849,"text":98},{"id":122,"depth":849,"text":123},{"id":163,"depth":849,"text":164},{"id":200,"depth":849,"text":201},{"id":224,"depth":849,"text":225,"children":855},[856,857,858,859],{"id":232,"depth":846,"text":233},{"id":278,"depth":846,"text":279},{"id":321,"depth":846,"text":322},{"id":342,"depth":846,"text":343},{"id":365,"depth":849,"text":366,"children":861},[862,863],{"id":372,"depth":846,"text":373},{"id":390,"depth":846,"text":391},{"id":454,"depth":849,"text":455,"children":865},[866,867],{"id":602,"depth":846,"text":603},{"id":674,"depth":846,"text":675},{"id":703,"depth":849,"text":704},{"id":721,"depth":849,"text":722,"children":870},[871,872,873,874,875,876],{"id":725,"depth":846,"text":726},{"id":732,"depth":846,"text":733},{"id":747,"depth":846,"text":748},{"id":761,"depth":846,"text":762},{"id":774,"depth":846,"text":775},{"id":793,"depth":846,"text":794},{"id":802,"depth":849,"text":803},"2026-06-28","Deploy without releasing, release without deploying. Three tracks shaped by one set of real constraints — and what misalignment between them really costs.",false,"md",{},true,"\u002Fbranching-release-deployment-alignment",{"title":6,"description":879},"branching-release-deployment-alignment\u002Findex",[888,889,890,891,892,893],"devops","branching","release-management","deployment-strategy","ci-cd","continuous-delivery","oxqMSbo5KcHv44Vvit0Ydq0ncNfwx5-EaBvCLrIVQow",{"id":896,"title":897,"author":7,"body":898,"date":1500,"description":1501,"draft":883,"extension":881,"lastUpdated":1500,"lastmod":1500,"meta":1502,"navigation":883,"path":1503,"seo":1504,"stem":1505,"tags":1506,"__hash__":1509},"posts\u002Fdeployment-strategies\u002Findex.md","Deployment Strategies: Progression, Delivery Mechanism, Cutover",{"type":9,"value":899,"toc":1482},[900,903,906,941,943,947,958,969,971,975,978,982,985,996,1000,1003,1007,1019,1021,1025,1124,1127,1133,1337,1342,1348,1354,1356,1360,1367,1376,1379,1382,1384,1388,1395,1405,1411,1424,1435,1437,1441,1444,1449,1451,1453,1457,1460,1462,1465,1469,1472,1476,1479],[12,901,897],{"id":902},"deployment-strategies-progression-delivery-mechanism-cutover",[16,904,905],{},"Two teams run the same deploy on the same Tuesday. At one, nobody looks up — the pipeline pushes, the canary soaks, traffic shifts, done before the coffee cools. At the other, the deploy has a war room, a conference bridge, and a rollback plan nobody has rehearsed. The difference isn't talent or tooling budget. It's that the first team made three separate deployment decisions on purpose, and the second inherited one big ceremony and never took it apart.",[26,907,908,912],{},[16,909,910],{},[31,911,33],{},[35,913,914,929,932,935,938],{},[38,915,916,917,920,921,924,925,928],{},"A deployment strategy is three independent choices: ",[31,918,919],{},"progression"," (which environments, which gates), ",[31,922,923],{},"delivery mechanism"," (push vs pull, immutable vs in-place), and ",[31,926,927],{},"cutover"," (how new code replaces old)",[38,930,931],{},"Cutover patterns trade capacity for rollback speed: blue-green buys instant rollback with double infrastructure; canary buys bounded blast radius with routing and observability; rolling is the cheap default with the slowest escape hatch",[38,933,934],{},"Deploy frequency is a stability practice, not a stability trade — risk scales with batch size, and a decade of DORA research shows frequent deployers fail less and recover faster",[38,936,937],{},"Canaries de-risk the deployment; feature flags de-risk the release — mature teams layer both",[38,939,940],{},"When customers run your software, deployment becomes pull-based: channels and rings replace pipelines, and the engineering investment moves into making the customer's cutover survivable",[51,942],{},[54,944,946],{"id":945},"deployment-is-not-release","Deployment Is Not Release",[16,948,949,950,954,955,339],{},"A deployment puts new code into a running environment. A release exposes that code to users. The two events can sit on separate timelines: code deploys Tuesday behind a ",[86,951,953],{"href":952},"\u002Ffeature-flags","feature flag"," set to off, soaks under real load for three days, and \"releases\" Friday as a configuration change. Everything in this post is about the first event — getting code safely into an environment. How the three timelines (branching, release, deployment) have to agree is the subject of the companion piece on ",[86,956,957],{"href":884},"why all three must align",[16,959,960,961,964,965,968],{},"That distinction does real work in this post: several patterns below look like release mechanisms but aren't. A canary routes traffic to a new ",[145,962,963],{},"build"," to answer \"is this deployment healthy?\" A flag exposes a ",[145,966,967],{},"feature"," to answer \"should users see this?\" Different questions, different layers, and the strongest setups answer both.",[51,970],{},[54,972,974],{"id":973},"the-three-axes-of-a-deployment-strategy","The Three Axes of a Deployment Strategy",[16,976,977],{},"\"What's your deployment strategy?\" is really three questions. Teams that answer them as one tend to inherit whichever answer their first deployment tool implied.",[230,979,981],{"id":980},"progression-which-environments-which-gates","Progression: which environments, which gates",[16,983,984],{},"Progression is the path code takes from merge to production — dev, staging, UAT, prod — and the gate at each hop: automated test suites, manual approval, soak time, compliance evidence. The design questions are which gates exist because of genuine risk or audit requirements, and which exist because nobody automated them. A useful audit: for each manual gate, name the failure it last caught. Gates that catch nothing are queues, not controls.",[16,986,987,988,991,992,995],{},"The artifact should be ",[31,989,990],{},"built once and promoted"," through the progression, not rebuilt per environment. Rebuilding introduces the possibility that what you tested is not what you shipped; promotion makes the artifact the unit of truth (",[86,993,142],{"href":140,"rel":994},[90]," treats this as foundational to continuous delivery).",[230,997,999],{"id":998},"delivery-mechanism-push-or-pull-immutable-or-in-place","Delivery mechanism: push or pull, immutable or in-place",[16,1001,1002],{},"Push pipelines (CI runs a deploy job against the environment) are the default and fine for most teams. Pull-based GitOps (the environment watches a declarative source and converges on it) buys an audit trail, drift correction, and a uniform rollback story — at the cost of another moving system. Orthogonally: immutable artifacts (replace the container, the VM image, the firmware slot) versus in-place updates (mutate the running environment). Immutable delivery makes rollback a redeploy of a known artifact instead of an archaeology project.",[230,1004,1006],{"id":1005},"cutover-how-new-code-replaces-old","Cutover: how new code replaces old",[16,1008,1009,1010,1014,1015,1018],{},"Cutover is the moment of replacement, and it's where the named patterns live — blue-green, canary, rolling, recreate, with shadow, ring, and A\u002FB as adjacent variants (",[86,1011,1013],{"href":182,"rel":1012},[90],"HashiCorp's zero-downtime guide"," covers the mechanics well). The next section compares them, but the framing matters more than the menu: ",[31,1016,1017],{},"cutover choice is an availability and rollback decision, not a feature-exposure decision."," If you're choosing canary percentages to control which users see a feature, you're using a deployment tool to do a release job — flags do it better.",[51,1020],{},[54,1022,1024],{"id":1023},"cutover-patterns-compared","Cutover Patterns Compared",[467,1026,1027,1046],{},[477,1028,1029],{},[481,1030,1031,1034,1037,1040,1043],{},[486,1032,1033],{},"Pattern",[486,1035,1036],{},"Mechanism",[486,1038,1039],{},"Rollback",[486,1041,1042],{},"What it costs",[486,1044,1045],{},"Best fit",[503,1047,1048,1067,1086,1105],{},[481,1049,1050,1055,1058,1061,1064],{},[513,1051,1052],{},[31,1053,1054],{},"Recreate",[513,1056,1057],{},"Stop old, start new",[513,1059,1060],{},"Redeploy old version (downtime)",[513,1062,1063],{},"Downtime window",[513,1065,1066],{},"Dev environments, batch systems, anything with a maintenance window",[481,1068,1069,1074,1077,1080,1083],{},[513,1070,1071],{},[31,1072,1073],{},"Rolling",[513,1075,1076],{},"Replace instances gradually",[513,1078,1079],{},"Roll forward or reverse the rollout (slow)",[513,1081,1082],{},"Version-skew tolerance during rollout",[513,1084,1085],{},"Stateless services, the Kubernetes default",[481,1087,1088,1093,1096,1099,1102],{},[513,1089,1090],{},[31,1091,1092],{},"Blue-green",[513,1094,1095],{},"Two full environments, switch traffic atomically",[513,1097,1098],{},"Switch back in seconds",[513,1100,1101],{},"Double capacity, double config drift surface",[513,1103,1104],{},"Monoliths, databases with careful migration discipline, anything where rollback speed is the priority",[481,1106,1107,1112,1115,1118,1121],{},[513,1108,1109],{},[31,1110,1111],{},"Canary",[513,1113,1114],{},"Route a small traffic slice to the new version, expand on health",[513,1116,1117],{},"Shift traffic back",[513,1119,1120],{},"Traffic routing, real observability, defined health criteria",[513,1122,1123],{},"High-traffic services where bugs surface under real load",[16,1125,1126],{},"Three things the table can't say:",[16,1128,1129,1132],{},[31,1130,1131],{},"Blue-green's atomicity is only as good as your release granularity."," Swapping environments in seconds is worth little if the deploy bundles dozens of changes and you can't tell which one broke production. Atomic infrastructure under a non-atomic batch is rollback theater — the swap is instant, the diagnosis still takes all night.",[1134,1135,470,1140,470,1144,470,1150,470,1159,470,470,1170,470,1177,470,470,1185,470,1193,470,1198,470,1202,470,1206,470,1210,470,1213,470,1217,470,1220,470,1224,470,1227,470,1231,470,1235,470,1240,470,470,1244,470,1249,470,1253,470,1258,470,470,1262,470,1270,470,1277,470,1283,470,470,1289,470,1294,470,470,1300,470,1303,470,1306,470,1310,470,470,1314,470,1318,470,1321,470,1324,470,470,1329,470,1333],"svg",{"viewBox":1136,"xmlns":1137,"role":267,"ariaLabel":1138,"style":1139},"0 0 580 320","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","Diagram showing a blue-green deployment fed by a monolithic release package of 47 unrelated changes merged over a month. The package deploys as one unit into the green environment, which goes live while blue stands by, and the two can swap atomically for rollback. But because the package bundles many unrelated changes, when production breaks there is no way to bisect which change is responsible. Atomic infrastructure cutover is wasted by a non-atomic release package.","max-width:580px;width:100%;background:#faf8f5;border-radius:8px;display:block;",[1141,1142,1143],"title",{},"Blue-Green Swap Meets a Monolithic Release Package",[1145,1146],"rect",{"width":1147,"height":1148,"fill":1149},"580","320","#fefdfb",[1145,1151],{"x":1152,"y":1152,"width":1153,"height":1154,"fill":1155,"stroke":1156,"strokeWidth":1157,"rx":1158},"0.5","579","319","none","#dcd6d1","1","8",[1160,1161,1169],"text",{"x":1162,"y":1163,"textAnchor":1164,"fill":1165,"fontSize":1166,"fontWeight":1167,"fontFamily":1168},"290","26","middle","#1a1511","13","600","'Instrument Sans','Inter Tight',-apple-system,sans-serif","Atomic Swap, Non-Atomic Package",[1160,1171,1176],{"x":1172,"y":1173,"textAnchor":1164,"fill":1165,"fontSize":1174,"fontWeight":1167,"fontFamily":1175},"106","52","12","'Inter Tight',-apple-system,sans-serif","Release package",[1145,1178],{"x":1179,"y":1180,"width":1181,"height":1182,"fill":1183,"stroke":1156,"strokeWidth":1157,"rx":1184},"36","60","140","176","#f2f0ec","6",[1145,1186],{"x":1187,"y":1188,"width":1189,"height":1190,"fill":1191,"rx":1192},"50","74","112","7","#c9c3bc","2",[1145,1194],{"x":1187,"y":1195,"width":1196,"height":1190,"fill":1197,"rx":1192},"87","92","#a8a29b",[1145,1199],{"x":1187,"y":1200,"width":1189,"height":1190,"fill":1201,"rx":1192},"100","#7f7974",[1145,1203],{"x":1187,"y":1204,"width":1205,"height":1190,"fill":1191,"rx":1192},"113","78",[1145,1207],{"x":1187,"y":1208,"width":1209,"height":1190,"fill":1197,"rx":1192},"126","104",[1145,1211],{"x":1187,"y":1212,"width":1189,"height":1190,"fill":1201,"rx":1192},"139",[1145,1214],{"x":1187,"y":1215,"width":1216,"height":1190,"fill":1191,"rx":1192},"152","86",[1145,1218],{"x":1187,"y":1219,"width":1189,"height":1190,"fill":1197,"rx":1192},"165",[1145,1221],{"x":1187,"y":1222,"width":1223,"height":1190,"fill":1201,"rx":1192},"178","96",[1145,1225],{"x":1187,"y":1226,"width":1189,"height":1190,"fill":1191,"rx":1192},"191",[1145,1228],{"x":1187,"y":1229,"width":1230,"height":1190,"fill":1197,"rx":1192},"204","70",[1145,1232],{"x":1187,"y":1233,"width":1234,"height":1190,"fill":1201,"rx":1192},"217","108",[1160,1236,1239],{"x":1172,"y":1237,"textAnchor":1164,"fill":1201,"fontSize":1238,"fontFamily":1175},"256","10","47 unrelated changes",[1160,1241,1243],{"x":1172,"y":1242,"textAnchor":1164,"fill":1201,"fontSize":1238,"fontFamily":1175},"269","merged over a month",[1245,1246],"line",{"x1":1222,"y1":1247,"x2":1248,"y2":1247,"stroke":1201,"strokeWidth":1192},"148","232",[1250,1251],"polygon",{"points":1252,"fill":1201},"232,148 224,143 224,153",[1160,1254,1257],{"x":1255,"y":1256,"textAnchor":1164,"fill":1201,"fontSize":1238,"fontFamily":1175},"205","132","deployed",[1160,1259,1261],{"x":1255,"y":1260,"textAnchor":1164,"fill":1201,"fontSize":1238,"fontFamily":1175},"143","as one unit",[1145,1263],{"x":1264,"y":1205,"width":1265,"height":1266,"fill":1267,"stroke":1268,"strokeWidth":1269,"rx":1184},"300","172","58","#e1efe6","#6a917a","1.5",[1271,1272],"circle",{"cx":1273,"cy":1274,"r":1275,"fill":1276},"318","98","4","#318454",[1160,1278,1282],{"x":1279,"y":1280,"textAnchor":1281,"fill":1165,"fontSize":1174,"fontWeight":1167,"fontFamily":1175},"332","102","start","GREEN",[1160,1284,1288],{"x":1285,"y":1286,"textAnchor":1164,"fill":1287,"fontSize":1238,"fontFamily":1175},"386","122","#47413c","new version — now live",[1271,1290],{"cx":1291,"cy":1292,"r":1158,"fill":1293},"466","84","#c53637",[1160,1295,1299],{"x":1291,"y":1296,"textAnchor":1164,"fill":1149,"fontSize":1297,"fontWeight":1298,"fontFamily":1175},"88","11","700","!",[1145,1301],{"x":1264,"y":1302,"width":1265,"height":1266,"fill":1183,"stroke":1191,"strokeWidth":1269,"rx":1184},"170",[1271,1304],{"cx":1273,"cy":1305,"r":1275,"fill":1191},"190",[1160,1307,1309],{"x":1279,"y":1308,"textAnchor":1281,"fill":1165,"fontSize":1174,"fontWeight":1167,"fontFamily":1175},"194","BLUE",[1160,1311,1313],{"x":1285,"y":1312,"textAnchor":1164,"fill":1287,"fontSize":1238,"fontFamily":1175},"214","previous — standby",[1245,1315],{"x1":1285,"y1":1316,"x2":1285,"y2":1317,"stroke":1287,"strokeWidth":1269},"138","168",[1250,1319],{"points":1320,"fill":1287},"386,138 381,146 391,146",[1250,1322],{"points":1323,"fill":1287},"386,168 381,160 391,160",[1160,1325,1328],{"x":1326,"y":1327,"textAnchor":1281,"fill":1287,"fontSize":1238,"fontFamily":1175},"486","156","atomic swap",[1160,1330,1332],{"x":1162,"y":1331,"textAnchor":1164,"fill":1276,"fontSize":1297,"fontFamily":1175},"286","✓ Atomic swap → rollback in seconds",[1160,1334,1336],{"x":1162,"y":1335,"textAnchor":1164,"fill":1293,"fontSize":1297,"fontFamily":1175},"306","✗ Non-atomic package → can't bisect which change broke prod",[16,1338,1339],{},[145,1340,1341],{},"The deployment mechanism is modern and the rollback is instant — but the release package is the weak link. Atomicity at the infrastructure layer buys nothing when 47 changes ship as a single indivisible unit.",[16,1343,1344,1347],{},[31,1345,1346],{},"Canary requires real health criteria, not vibes."," A canary without defined success metrics (error rate, latency percentiles, business signals) and an automated decision is just a slow rollout with extra steps. The observability investment is the actual cost; the routing is the easy part.",[16,1349,1350,1353],{},[31,1351,1352],{},"Shadow, ring, and A\u002FB are answers to different questions."," Shadow (mirror traffic to the new version, discard responses) tests behavior without risk. Ring deployment (ordered cohorts — internal, beta, everyone) is progression applied to populations. A\u002FB testing is an experimentation method that happens to share routing machinery — it measures product outcomes, not deployment health.",[51,1355],{},[54,1357,1359],{"id":1358},"deploy-frequency-is-a-stability-practice","Deploy Frequency Is a Stability Practice",[16,1361,1362,1363,1366],{},"The most common reason teams deploy rarely is fear of errors and downtime — and the fear is rational, because every deploy a monthly-deploying team has ever run genuinely was dangerous. Each one carried a month of changes. The risk was real; it was just attributed to the wrong variable. Deployment risk scales with ",[31,1364,1365],{},"batch size",", not deployment count — a team that has never seen a small deploy has \"deploy\" and \"big risky event\" fused in its experience. And a calendar that defers deploys doesn't reduce the risk; it concentrates it into one compound event where any failure has forty possible causes.",[16,1368,1369,1370,1372,1373,185],{},"This is the most consistent finding in a decade of DORA research: throughput and stability are not a trade-off. Teams that deploy more frequently have ",[145,1371,328],{}," change failure rates and recover faster, while low performers are slow and unstable at the same time (",[86,1374,334],{"href":332,"rel":1375},[90],[16,1377,1378],{},"The mechanism is mundane. One change deployed means one suspect when something breaks. A dark deploy behind a flag removes user exposure from the deploy event, and the residual risk classes it leaves — migrations, startup paths — are exactly what canary and blue-green exist to bound. A deploy that happens daily is rehearsed machinery; one that happens monthly is a ceremony whose failure modes nobody has recently exercised. Reluctance feeds the loop it fears: infrequent deploys mean bigger batches, bigger batches fail more, failures add approval gates, and the gates make deploys rarer still.",[16,1380,1381],{},"The on-ramp for a reluctant team never requires accepting more user-facing risk than it takes today: automate the pipeline and deploy continuously to staging first, which builds the muscle at zero production stakes; add a flag platform; then shrink the production batch — monthly to fortnightly to weekly — while the release cadence stays wherever the business needs it. The path is paved with smaller batches, not a bigger appetite for risk.",[51,1383],{},[54,1385,1387],{"id":1386},"when-you-dont-own-production","When You Don't Own Production",[16,1389,1390,1391,1394],{},"For versioned products — CLIs, SDKs, operators, on-prem installs, embedded firmware — the customer's upgrade ",[145,1392,1393],{},"is"," the production deployment, and the vendor's deployment strategy splits in two.",[16,1396,1397,1400,1401,1404],{},[31,1398,1399],{},"What you control:"," build-once, promote-many. Each tagged release is built exactly once as a signed, immutable artifact and promoted through internal environments, with every supported release line running the identical pipeline. Distribution is pull-based — a registry, package repo, or marketplace — and your staged rollout becomes ",[31,1402,1403],{},"channel-based availability",": alpha, beta, and stable rings, where you control when a version becomes available to each ring and the customer controls when it's installed. Dogfood and beta-channel customers are your canary.",[16,1406,1407,1410],{},[31,1408,1409],{},"What you can only make survivable:"," the customer's cutover. The investment goes into rollback-engineering the artifact itself — reversible or stepwise migrations, a documented and tested downgrade path, version-skew tolerance so mixed-version states during upgrade don't break, and for device fleets, A\u002FB dual-partition updates: blue-green pushed down to the device, with automatic rollback to the old slot on boot failure.",[16,1412,1413,1416,1417,1420,1421,1423],{},[31,1414,1415],{},"What you give up:"," flag-based progressive delivery — you can't flip a flag in an air-gapped install. So the de-risking SaaS does ",[145,1418,1419],{},"after"," deploy (canary, percentage rollouts) has to move ",[145,1422,443],{}," release: internal soak, beta channels, and the full regression matrix across every supported line stand in for post-deploy canaries. The trade is coherent rather than unfortunate — the same consumption constraint that forces the branch structure also pulls the risk controls earlier in the pipeline.",[16,1425,1426,1427,1430,1431,1434],{},"A hybrid case sits between: vendor-managed environments with strict per-customer deployment requirements (change windows, CAB approvals, freezes). There, deployment ",[145,1428,1429],{},"mechanics"," return to your control — flags work again, so customer version-pinning can become flag-pinning on a current binary — while ",[145,1432,1433],{},"timing"," stays contractual. Customers' windows become your rings, ordered by risk appetite, and a contractual skew cap (upgrades accepted within 90 days, max N−1 behind) keeps the fleet from diverging into the unbounded-maintenance trap.",[51,1436],{},[54,1438,1440],{"id":1439},"choosing-derive-it-from-your-constraints","Choosing: Derive It from Your Constraints",[16,1442,1443],{},"The pattern menu is the least important part of this post. The deployment strategy that works is the one derived from constraints you can name: the rollback time your business actually tolerates, the capacity you can actually double, the observability you actually have, who actually owns the production environment. A team that picks canary because it's what good teams do — without the health criteria to make canary decisions — built a slower rolling update. A team that runs recreate with a maintenance window because its batch system genuinely has one is better aligned than either.",[16,1445,1446,1447,339],{},"And the deployment strategy never stands alone. It has to agree with how code converges and how users see it — the full argument is in ",[86,1448,6],{"href":884},[51,1450],{},[54,1452,722],{"id":721},[230,1454,1456],{"id":1455},"whats-the-difference-between-blue-green-and-canary-deployment","What's the difference between blue-green and canary deployment?",[16,1458,1459],{},"Blue-green runs two full environments and switches all traffic atomically, optimizing for instant rollback at the cost of double capacity. Canary routes a small, growing slice of traffic to the new version, optimizing for bounded blast radius at the cost of routing infrastructure and real health metrics. Blue-green answers \"can I get back fast?\"; canary answers \"is this build healthy under real load?\"",[230,1461,748],{"id":747},[16,1463,1464],{},"No — deployment risk scales with batch size, not deployment count. A decade of DORA research shows teams that deploy more frequently have lower change failure rates and recover faster, because small batches shrink blast radius, simplify diagnosis, and keep deployment machinery rehearsed. Deploying dark behind a feature flag removes user exposure from the deploy event entirely.",[230,1466,1468],{"id":1467},"do-i-need-kubernetes-to-run-canary-deployments","Do I need Kubernetes to run canary deployments?",[16,1470,1471],{},"No. Canary requires traffic routing with weighted distribution and health observability — a load balancer with weighted target groups, a service mesh, or an edge\u002FCDN layer all work. Kubernetes makes rolling updates the default and canary convenient via ingress controllers or meshes, but the pattern predates it.",[230,1473,1475],{"id":1474},"what-deployment-strategy-fits-versioned-products-customers-install-themselves","What deployment strategy fits versioned products customers install themselves?",[16,1477,1478],{},"Build-once\u002Fpromote-many with an identical pipeline per supported release line, pull-based channel distribution (alpha\u002Fbeta\u002Fstable rings), and rollback-engineered artifacts: reversible migrations, tested downgrade paths, version-skew tolerance, and A\u002FB partition updates for devices. Progressive delivery moves before the release — internal soak and beta channels replace post-deploy canaries.",[840,1480,1481],{"type":842},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What's the difference between blue-green and canary deployment?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Blue-green runs two full environments and switches all traffic atomically, optimizing for instant rollback at the cost of double capacity. Canary routes a small, growing slice of traffic to the new version, optimizing for bounded blast radius at the cost of routing infrastructure and real health metrics. Blue-green answers 'can I get back fast?'; canary answers 'is this build healthy under real load?'\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Isn't deploying to production more often riskier?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No — deployment risk scales with batch size, not deployment count. A decade of DORA research shows teams that deploy more frequently have lower change failure rates and recover faster, because small batches shrink blast radius, simplify diagnosis, and keep deployment machinery rehearsed. Deploying dark behind a feature flag removes user exposure from the deploy event entirely.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Do I need Kubernetes to run canary deployments?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"No. Canary requires traffic routing with weighted distribution and health observability — a load balancer with weighted target groups, a service mesh, or an edge\u002FCDN layer all work. Kubernetes makes rolling updates the default and canary convenient via ingress controllers or meshes, but the pattern predates it.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What deployment strategy fits versioned products customers install themselves?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Build-once\u002Fpromote-many with an identical pipeline per supported release line, pull-based channel distribution (alpha\u002Fbeta\u002Fstable rings), and rollback-engineered artifacts: reversible migrations, tested downgrade paths, version-skew tolerance, and A\u002FB partition updates for devices. Progressive delivery moves before the release — internal soak and beta channels replace post-deploy canaries.\"\n      }\n    }\n  ]\n}\n",{"title":845,"searchDepth":846,"depth":846,"links":1483},[1484,1485,1490,1491,1492,1493,1494],{"id":945,"depth":849,"text":946},{"id":973,"depth":849,"text":974,"children":1486},[1487,1488,1489],{"id":980,"depth":846,"text":981},{"id":998,"depth":846,"text":999},{"id":1005,"depth":846,"text":1006},{"id":1023,"depth":849,"text":1024},{"id":1358,"depth":849,"text":1359},{"id":1386,"depth":849,"text":1387},{"id":1439,"depth":849,"text":1440},{"id":721,"depth":849,"text":722,"children":1495},[1496,1497,1498,1499],{"id":1455,"depth":846,"text":1456},{"id":747,"depth":846,"text":748},{"id":1467,"depth":846,"text":1468},{"id":1474,"depth":846,"text":1475},"2026-06-12","A deployment strategy is three choices, not one. How blue-green, canary, rolling, and pull-based delivery fit together — and why deploy frequency is a stability practice.",{},"\u002Fdeployment-strategies",{"title":897,"description":1501},"deployment-strategies\u002Findex",[888,891,892,893,1507,1508],"blue-green","canary","nqWBrRzp6qcyPsbtImYPIBDN5xFiNzpUpgB3H4YZhwU",{"id":1511,"title":1512,"author":1513,"body":1514,"date":1871,"description":1872,"draft":883,"extension":881,"lastUpdated":1871,"lastmod":1871,"meta":1873,"navigation":883,"path":952,"seo":1874,"stem":1875,"tags":1876,"__hash__":1880},"posts\u002Ffeature-flags\u002Findex.md","[DRAFT] Feature Flags: The Operational Layer Between Deploy and Release","Stratern Engineering",{"type":9,"value":1515,"toc":1850},[1516,1524,1530,1564,1566,1570,1574,1585,1587,1591,1595,1620,1622,1626,1630,1650,1652,1656,1660,1680,1682,1686,1691,1731,1733,1737,1741,1755,1757,1761,1765,1785,1787,1789,1795,1799,1805,1810,1816,1821,1827,1831,1837,1842,1844],[12,1517,1519,1523],{"id":1518},"draft-feature-flags-the-operational-layer-between-deploy-and-release",[1520,1521,1522],"span",{},"DRAFT"," Feature Flags: The Operational Layer Between Deploy and Release",[16,1525,1526,1529],{},[1520,1527,1528],{},"PLACEHOLDER intro — 2-3 paragraphs","\nPitch angle: most feature-flag content treats flags as a toggle library. This post treats them as the operational layer that makes deploy\u002Frelease decoupling actually work — and as something with real operational weight (flag debt, governance, lifecycle) that teams underestimate. Positions the post as the practitioner companion to the branching\u002Frelease\u002Fdeployment post.",[26,1531,1532,1536],{},[16,1533,1534],{},[31,1535,33],{},[35,1537,1538,1544,1549,1554,1559],{},[38,1539,1540,1543],{},[1520,1541,1542],{},"PLACEHOLDER"," Feature flags are the runtime mechanism that decouples deployment from release",[38,1545,1546,1548],{},[1520,1547,1542],{}," At least four flag categories exist (release, ops, experiment, permission) and they have different lifecycles",[38,1550,1551,1553],{},[1520,1552,1542],{}," Flag debt is the silent cost — flags outlive their purpose and accumulate as dead conditional logic",[38,1555,1556,1558],{},[1520,1557,1542],{}," Build-vs-buy depends on rule complexity, audit needs, and how many teams need self-service",[38,1560,1561,1563],{},[1520,1562,1542],{}," One named owner per flag, one expected removal date, or it becomes permanent infrastructure",[51,1565],{},[54,1567,1569],{"id":1568},"what-feature-flags-are-and-arent","What Feature Flags Are (And Aren't)",[16,1571,1572],{},[1520,1573,1542],{},[35,1575,1576,1579,1582],{},[38,1577,1578],{},"Definition: a runtime check that returns a value (boolean or variant) based on context",[38,1580,1581],{},"Distinguish from: build-time config, environment variables, branches, A\u002FB testing tools, entitlement systems",[38,1583,1584],{},"Why the distinction matters: each has different latency to change, different audit story, different blast radius",[51,1586],{},[54,1588,1590],{"id":1589},"why-you-actually-need-them","Why You Actually Need Them",[16,1592,1593],{},[1520,1594,1542],{},[35,1596,1597,1605,1608,1611,1614,1617],{},[38,1598,1599,1600,1604],{},"Decouple deployment from release (link to ",[86,1601,1603],{"href":1602},"\u002Fblog\u002Fbranching-release-deployment-alignment","branching-release-deployment-alignment",")",[38,1606,1607],{},"Progressive rollout (canary at the release layer, not just infrastructure)",[38,1609,1610],{},"Kill switches for risky code paths",[38,1612,1613],{},"Entitlements and plan gating",[38,1615,1616],{},"Experiments and A\u002FB tests",[38,1618,1619],{},"Trunk-based development enabler (merge half-finished work safely)",[51,1621],{},[54,1623,1625],{"id":1624},"how-they-work-under-the-hood","How They Work Under the Hood",[16,1627,1628],{},[1520,1629,1542],{},[35,1631,1632,1635,1638,1641,1644,1647],{},[38,1633,1634],{},"SDK call with user\u002Frequest context",[38,1636,1637],{},"Flag service as rules engine",[38,1639,1640],{},"Sticky bucketing (consistent user experience)",[38,1642,1643],{},"Streaming vs polling updates",[38,1645,1646],{},"Local evaluation vs remote evaluation",[38,1648,1649],{},"Fallback values when the flag service is unreachable",[51,1651],{},[54,1653,1655],{"id":1654},"targeting-who-sees-what","Targeting: Who Sees What",[16,1657,1658],{},[1520,1659,1542],{},[35,1661,1662,1665,1668,1671,1674,1677],{},[38,1663,1664],{},"Percentage rollout (hash-bucketed, sticky)",[38,1666,1667],{},"Attribute rules (plan, country, app version, account age)",[38,1669,1670],{},"Named segments and cohorts",[38,1672,1673],{},"Individual allowlist for specific users",[38,1675,1676],{},"Layered rollout patterns (internal → beta → 1% → 100%)",[38,1678,1679],{},"Context attributes beyond the user (device, region, time)",[51,1681],{},[54,1683,1685],{"id":1684},"the-operational-reality-flag-debt","The Operational Reality: Flag Debt",[16,1687,1688],{},[1520,1689,1690],{},"PLACEHOLDER — this is the section most posts skip",[35,1692,1693,1696,1725,1728],{},[38,1694,1695],{},"Flags accumulate; cleanup is nobody's job by default",[38,1697,1698,1699],{},"Flag categories and their lifecycles:\n",[35,1700,1701,1707,1713,1719],{},[38,1702,1703,1706],{},[31,1704,1705],{},"Release flags"," — short-lived, days to weeks, removed after 100% rollout",[38,1708,1709,1712],{},[31,1710,1711],{},"Ops flags"," — long-lived, kill switches and circuit breakers",[38,1714,1715,1718],{},[31,1716,1717],{},"Experiment flags"," — bounded by experiment duration",[38,1720,1721,1724],{},[31,1722,1723],{},"Permission flags"," — should migrate to a real entitlement system once stable",[38,1726,1727],{},"Governance: ownership, expiry dates, automated stale-flag detection",[38,1729,1730],{},"The cost of orphan flags: dead conditional branches, false test coverage, security surface",[51,1732],{},[54,1734,1736],{"id":1735},"build-vs-buy","Build vs Buy",[16,1738,1739],{},[1520,1740,1542],{},[35,1742,1743,1746,1749,1752],{},[38,1744,1745],{},"DIY: a Redis key + admin UI works for simple boolean flags at small scale",[38,1747,1748],{},"When DIY breaks down: multi-tenant rules, audit requirements, percentage rollout at scale, non-engineer self-service",[38,1750,1751],{},"Platform options to discuss: LaunchDarkly, Flagsmith, Unleash, Statsig, GrowthBook, ConfigCat, plus cloud-native (AWS AppConfig, Azure App Configuration)",[38,1753,1754],{},"Migration trap: starting DIY, growing past it, then having to retrofit rules and audit history",[51,1756],{},[54,1758,1760],{"id":1759},"common-anti-patterns","Common Anti-Patterns",[16,1762,1763],{},[1520,1764,1542],{},[35,1766,1767,1770,1773,1776,1779,1782],{},[38,1768,1769],{},"Flags as long-lived branches (using flags to avoid integration, not to control release)",[38,1771,1772],{},"Nested flag conditionals (combinatorial explosion of states)",[38,1774,1775],{},"Flags without an owner or removal date",[38,1777,1778],{},"Permission gating via release flags (should be a real entitlement service)",[38,1780,1781],{},"Forgetting flags exist in mobile clients that never updated",[38,1783,1784],{},"Treating flag flips as untracked changes (no audit trail, no rollback narrative)",[51,1786],{},[54,1788,722],{"id":721},[230,1790,1792,1794],{"id":1791},"placeholder-whats-the-difference-between-a-feature-flag-and-a-config-value",[1520,1793,1542],{}," What's the difference between a feature flag and a config value?",[16,1796,1797],{},[1520,1798,1542],{},[230,1800,1802,1804],{"id":1801},"placeholder-do-feature-flags-slow-down-my-application",[1520,1803,1542],{}," Do feature flags slow down my application?",[16,1806,1807],{},[1520,1808,1809],{},"PLACEHOLDER — cover SDK overhead, caching, local evaluation",[230,1811,1813,1815],{"id":1812},"placeholder-how-do-i-test-code-thats-behind-a-feature-flag",[1520,1814,1542],{}," How do I test code that's behind a feature flag?",[16,1817,1818],{},[1520,1819,1820],{},"PLACEHOLDER — both states, integration tests, flag override in test harness",[230,1822,1824,1826],{"id":1823},"placeholder-when-should-i-remove-a-feature-flag",[1520,1825,1542],{}," When should I remove a feature flag?",[16,1828,1829],{},[1520,1830,1542],{},[230,1832,1834,1836],{"id":1833},"placeholder-can-feature-flags-replace-branching",[1520,1835,1542],{}," Can feature flags replace branching?",[16,1838,1839],{},[1520,1840,1841],{},"PLACEHOLDER — short answer: no, they complement it; long answer ties back to branching strategies post",[51,1843],{},[16,1845,1846,1849],{},[1520,1847,1848],{},"PLACEHOLDER closing","\nTie back to the alignment frame: feature flags are infrastructure, not a library you bolt on. The teams that get the most out of decoupling deploy from release are the ones that treat flag hygiene with the same rigor as any other production system.",{"title":845,"searchDepth":846,"depth":846,"links":1851},[1852,1853,1854,1855,1856,1857,1858,1859],{"id":1568,"depth":849,"text":1569},{"id":1589,"depth":849,"text":1590},{"id":1624,"depth":849,"text":1625},{"id":1654,"depth":849,"text":1655},{"id":1684,"depth":849,"text":1685},{"id":1735,"depth":849,"text":1736},{"id":1759,"depth":849,"text":1760},{"id":721,"depth":849,"text":722,"children":1860},[1861,1863,1865,1867,1869],{"id":1791,"depth":846,"text":1862},"PLACEHOLDER What's the difference between a feature flag and a config value?",{"id":1801,"depth":846,"text":1864},"PLACEHOLDER Do feature flags slow down my application?",{"id":1812,"depth":846,"text":1866},"PLACEHOLDER How do I test code that's behind a feature flag?",{"id":1823,"depth":846,"text":1868},"PLACEHOLDER When should I remove a feature flag?",{"id":1833,"depth":846,"text":1870},"PLACEHOLDER Can feature flags replace branching?","2026-06-06","DRAFT — structural skeleton only. Not for reference, citation, or internal linking by other agents until promoted to draft:false.",{},{"title":1512,"description":1872},"feature-flags\u002Findex",[888,1877,890,1878,1879],"feature-flags","progressive-delivery","draft","r20yw5uSCZPRAmOWUWJCKGbPz6FZfIw4q3GDIusvNfI",{"id":1882,"title":1883,"author":1513,"body":1884,"date":3179,"description":3180,"draft":883,"extension":881,"lastUpdated":3179,"lastmod":3179,"meta":3181,"navigation":883,"path":3182,"seo":3183,"stem":3184,"tags":3185,"__hash__":3188},"posts\u002Fgit-branching-strategies\u002Findex.md","Git Branching Strategies in 2025: Choose by Evidence, Not Convention",{"type":9,"value":1885,"toc":3154},[1886,1889,1910,1913,1940,1942,1946,1949,1955,1977,1983,1994,1996,2000,2004,2007,2013,2019,2031,2034,2043,2051,2055,2064,2067,2072,2077,2082,2086,2089,2092,2097,2102,2107,2111,2125,2132,2135,2143,2152,2155,2157,2161,2169,2178,2330,2340,2349,2352,2476,2490,2493,2495,2499,2502,2701,2721,2725,2728,2733,2744,2749,2760,2765,2776,2781,2792,2797,2817,2820,2822,2826,2835,2838,2841,2844,2853,2864,2990,2999,3001,3005,3008,3012,3018,3024,3030,3036,3040,3045,3050,3055,3060,3066,3074,3076,3078,3082,3089,3093,3096,3100,3113,3117,3125,3129,3132,3134,3137,3140,3151],[12,1887,1883],{"id":1888},"git-branching-strategies-in-2025-choose-by-evidence-not-convention",[16,1890,1891,1892,1897,1898,1903,1904,1909],{},"Elite DevOps teams deploy ",[86,1893,1896],{"href":1894,"rel":1895},"https:\u002F\u002Fdora.dev\u002Fresearch\u002F2024\u002Fdora-report\u002F",[90],"182 times more frequently"," than low performers and recover from failures ",[86,1899,1902],{"href":1900,"rel":1901},"https:\u002F\u002Flaunchdarkly.com\u002Fblog\u002Felite-performance-with-trunk-based-development\u002F",[90],"2,293 times faster",". They also carry a ",[86,1905,1908],{"href":1906,"rel":1907},"https:\u002F\u002Foctopus.com\u002Fblog\u002F2024-devops-performance-clusters",[90],"5% change failure rate"," against their peers' 40-64%. That gap isn't a cloud provider problem. It isn't a programming language problem. It's a git branching strategies problem, and most engineering leaders inherit theirs rather than choose it.",[16,1911,1912],{},"This post compares the four dominant git branching strategies, what the DORA research actually shows, and how to score your team's readiness before you commit to a migration.",[26,1914,1915,1919],{},[16,1916,1917],{},[31,1918,33],{},[35,1920,1921,1928,1931,1934,1937],{},[38,1922,1923,1924,1604],{},"Elite teams are 2.3x more likely to use trunk-based development (",[86,1925,1927],{"href":1900,"rel":1926},[90],"DORA 2021",[38,1929,1930],{},"Gitflow's creator publicly recommends against it for continuous delivery teams",[38,1932,1933],{},"Long-lived branches accumulate merge conflicts. 1 in 5 merges cause conflicts, and manual conflicts produce 26x more bugs",[38,1935,1936],{},"Your branching strategy determines your feedback loop length, merge cost, and deployment independence",[38,1938,1939],{},"Score your team on 4 readiness dimensions before migrating to trunk-based development",[51,1941],{},[54,1943,1945],{"id":1944},"what-your-branching-strategy-actually-controls","What Your Branching Strategy Actually Controls",[16,1947,1948],{},"Your branching strategy is an architectural decision. It controls how quickly developers get feedback, how much merge cost accumulates before integration, and how independently teams can deploy. Most teams treat it as a convention inherited from a previous job. The research suggests that's a costly default.",[16,1950,1951,1954],{},[31,1952,1953],{},"Feedback loop length."," A long-lived feature branch delays integration feedback by the lifetime of that branch: days, weeks, sometimes longer. By the time it merges, the codebase it diverged from no longer exists.",[16,1956,1957,1960,1961,1966,1967,1972,1973,185],{},[31,1958,1959],{},"Merge cost accumulation."," A ",[86,1962,1965],{"href":1963,"rel":1964},"https:\u002F\u002Farxiv.org\u002Fpdf\u002F1907.06274",[90],"2019 analysis of open-source repositories"," found that roughly 1 in 5 merges (19.32% average) cause conflicts, with 8-21% of merge trials failing outright. The cost compounds. Code near merge conflicts is ",[86,1968,1971],{"href":1969,"rel":1970},"https:\u002F\u002Fdoi.org\u002F10.1007\u002Fs10664-019-09784-5",[90],"2x more likely to contain a bug",". When a conflict requires manual intervention, that code is 26x more likely to harbor a defect (",[86,1974,1976],{"href":1969,"rel":1975},[90],"Empirical Software Engineering, Springer, 2019",[16,1978,1979,1982],{},[31,1980,1981],{},"Deployment independence."," Branch topology directly controls whether a team can ship without coordinating with another team's merge schedule. That coordination tax is invisible until it isn't.",[26,1984,1985],{},[16,1986,1987,84,1989,1993],{},[31,1988,116],{},[86,1990,1992],{"href":1991},"\u002Fblog\u002Fci-cd-pipeline-architecture","CI\u002FCD Pipeline Architecture",". How pipeline design interacts with your branching model.",[51,1995],{},[54,1997,1999],{"id":1998},"the-four-strategies","The Four Strategies",[230,2001,2003],{"id":2002},"gitflow","Gitflow",[16,2005,2006],{},"Vincent Driessen published Gitflow in 2010 to solve a real problem: shipping versioned software on a schedule when continuous deployment wasn't feasible. The model introduces two permanent branches (main, develop), three supporting branch types (feature, release, hotfix), and a well-defined merge ceremony between them.",[16,2008,2009,2012],{},[31,2010,2011],{},"The honest use case."," Gitflow still belongs in specific contexts: versioned desktop or embedded software, libraries that must support multiple released versions simultaneously, and environments with regulatory release gates requiring a formal staging period before production.",[16,2014,2015,2018],{},[31,2016,2017],{},"The anti-pattern signal."," If your team maintains a develop-to-main divergence that feels like a side project, if PR backlogs routinely exceed a week, or if you've ever described your release branch as \"almost stable for the past three weeks\", Gitflow is working against you.",[16,2020,2021,2024,2025,2030],{},[31,2022,2023],{},"CI\u002FCD alignment."," Gitflow produces pipelines that build and test per branch in isolation, integrating late. This structure is incompatible with deploy-on-merge workflows. ",[86,2026,2029],{"href":2027,"rel":2028},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fprescriptive-guidance\u002Flatest\u002Fchoosing-git-branch-approach\u002Fadvantages-and-disadvantages-of-the-gitflow-strategy.html",[90],"AWS Prescriptive Guidance"," lists four explicit disadvantages: complexity, CD incompatibility, branch management overhead, and technical debt accumulation.",[16,2032,2033],{},"The most notable critique comes from Gitflow's creator himself. In March 2020, Vincent Driessen added a note to his original post:",[26,2035,2036],{},[16,2037,2038,2039,1604],{},"\"If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team.\" (",[86,2040,2042],{"href":260,"rel":2041},[90],"nvie.com, March 2020",[16,2044,2045,2050],{},[86,2046,2049],{"href":2047,"rel":2048},"https:\u002F\u002Fthoughtworks.com\u002Fradar\u002Ftechniques\u002Ffeature-branching",[90],"ThoughtWorks Technology Radar"," has placed feature branching in \"Hold.\" That's not a footnote. It's a directional signal from practitioners who evaluate tooling across hundreds of enterprise engagements.",[230,2052,2054],{"id":2053},"github-flow","GitHub Flow",[16,2056,2057,2058,2063],{},"Scott Chacon, then a GitHub co-founder, published GitHub Flow on ",[86,2059,2062],{"href":2060,"rel":2061},"https:\u002F\u002Fscottchacon.com\u002F2011\u002F08\u002F31\u002Fgithub-flow\u002F",[90],"August 31, 2011"," because GitHub was already deploying to production multiple times daily and Gitflow introduced complexity the team didn't need.",[16,2065,2066],{},"The model has six rules: main is always deployable; branches have descriptive names; developers push frequently; pull requests drive feedback; peer review is required before merge; and deployment happens immediately after merge to main.",[16,2068,2069,2071],{},[31,2070,2011],{}," GitHub Flow fits SaaS products, web applications, and teams of roughly 5-30 engineers who deploy continuously. It's the right default for most product teams that don't have a specific reason to choose something else.",[16,2073,2074,2076],{},[31,2075,2017],{}," If you have multiple deployment environments with mandatory sign-off between them (staging to UAT to production, for example), GitHub Flow provides no mechanism for that gate. You'll build it ad hoc in your pipeline, which is exactly the problem GitLab Flow was designed to solve.",[16,2078,2079,2081],{},[31,2080,2023],{}," Deploy-on-merge triggers pair naturally with GitHub Flow. Feature flags fill the gap for in-progress work: the branch merges when the code is ready, not when the feature is ready.",[230,2083,2085],{"id":2084},"gitlab-flow","GitLab Flow",[16,2087,2088],{},"GitLab Flow sits deliberately between GitHub Flow's simplicity and Gitflow's structure. It earned its place by solving the environment gate problem without reintroducing Gitflow's branch proliferation.",[16,2090,2091],{},"The model introduces environment branches (typically main, staging, and production) with one non-negotiable rule: commits always flow downstream. You never push directly to staging or production. You promote code by merging forward through the chain.",[16,2093,2094,2096],{},[31,2095,2011],{}," Teams with mandatory pre-production sign-off, SOC 2 or PCI DSS audit requirements, or multiple deployment environments where each represents a distinct stakeholder approval step. A compliance officer's signature on staging before production is a legitimate business requirement, and GitLab Flow handles it without ceremony.",[16,2098,2099,2101],{},[31,2100,2017],{}," If you don't actually need the environment gates, GitLab Flow adds process without benefit. A team that promotes code from staging to production on every commit without human review is using GitHub Flow with extra steps.",[16,2103,2104,2106],{},[31,2105,2023],{}," Each downstream merge triggers the appropriate environment pipeline. The audit trail is the merge history itself: a clean answer for regulated teams who need to demonstrate what shipped when and who approved it.",[230,2108,2110],{"id":2109},"trunk-based-development","Trunk-Based Development",[16,2112,2113,2114,2119,2120,339],{},"Trunk-based development (TBD) traces its origins to Extreme Programming in the 1990s. Paul Hammant codified the modern practice at ",[86,2115,2118],{"href":2116,"rel":2117},"https:\u002F\u002Ftrunkbaseddevelopment.com",[90],"trunkbaseddevelopment.com",". Nicole Forsgren, Jez Humble, and Gene Kim validated it empirically in ",[86,2121,2124],{"href":2122,"rel":2123},"https:\u002F\u002Fabseil.io\u002Fresources\u002Fswe-book\u002Fhtml\u002Fch16.html",[90],"Accelerate (2018)",[16,2126,2127,2131],{},[86,2128,2130],{"href":768,"rel":2129},[90],"DORA defines TBD"," precisely: no more than three active branches in the repository, merges to trunk at least once daily, no code freezes, and no integration phases. That precision matters. Many teams claim TBD while quietly maintaining week-long branches.",[16,2133,2134],{},"Two valid variants exist. For teams of two to five experienced developers, direct commits to trunk are appropriate. For larger teams, short-lived branches capped at hours (48 hours absolute maximum) with required code review before merge are the correct approach.",[16,2136,2137,2138,2142],{},"The scale proof point is hard to argue with. Google operates a single monorepo housing code for 50,000 engineers, absorbing 60,000 to 70,000 commits per working day. Approximately 2 of every 1,000 teams maintain long-lived branches, and ",[86,2139,2141],{"href":2122,"rel":2140},[90],"Google Software Engineering"," documents this as a deliberate, maintained exception rather than a norm.",[16,2144,2145,2146,2151],{},"A ",[86,2147,2150],{"href":2148,"rel":2149},"https:\u002F\u002Farxiv.org\u002Fhtml\u002F2507.08943v1",[90],"2025 arXiv preprint"," surveying 50 developers found that TBD practitioners have a median of roughly 10 years of experience versus roughly 7 years for branch-based developers. TBD teams typically cap at around 5 members versus up to 20 for branch-based workflows. Only 12% of respondents used TBD. 84% used branch-based workflows. The Brazilian sample and small n make this directional, not conclusive. But the experience gap reflects a real maturity requirement, and that's the part most \"just adopt TBD\" advice quietly skips.",[16,2153,2154],{},"TBD requires three non-negotiable preconditions: mature automated testing, feature flags for any work that isn't complete at merge time, and a team culture that treats small, frequent commits as a professional norm rather than an interruption.",[51,2156],{},[54,2158,2160],{"id":2159},"what-the-data-actually-says-dora-evidence","What the Data Actually Says (DORA Evidence)",[16,2162,2163,2164,2168],{},"DORA metrics measure four things: deployment frequency, change lead time, change failure rate, and mean time to restore. They correlate with branching strategy more directly than most practitioners expect. The 2021 DORA research found that elite performers meeting reliability targets are ",[86,2165,2167],{"href":1900,"rel":2166},[90],"2.3 times more likely to use trunk-based development",". That's a correlation, not a controlled experiment. It's also the best longitudinal signal the industry has.",[16,2170,2171,2172,2177],{},"The 2024 performance tier distribution tells a more troubling story. Elite performers grew from 18% to ",[86,2173,2176],{"href":2174,"rel":2175},"https:\u002F\u002Fgetdx.com\u002Fblog\u002F2024-dora-report\u002F",[90],"19% of teams surveyed",". High performers dropped from 31% to 22%. Low performers grew from 17% to 25%. The middle is thinning. The tail is growing.",[1134,2179,470,2182,470,2185,470,470,2188,470,470,2193,470,2199,470,2203,470,2206,470,470,2210,470,2214,470,2218,470,2222,470,470,2226,470,2230,470,2233,470,2237,470,2241,470,2244,470,2247,470,2251,470,2254,470,2258,470,470,470,2261,470,2266,470,470,2270,470,2274,470,470,470,2278,470,2281,470,470,2286,470,2291,470,470,470,2296,470,2300,470,470,2304,470,2308,470,470,470,2311,470,2315,470,470,2320,470,2325],{"viewBox":1136,"xmlns":1137,"role":267,"ariaLabel":2180,"style":2181},"Horizontal grouped bar chart comparing DORA performance tier distribution in 2023 versus 2024. Elite grew from 18% to 19%. High dropped from 31% to 22%. Medium stayed at 34%. Low grew from 17% to 25%.","max-width:580px;width:100%;background:#1a1a2e;border-radius:8px;display:block;",[1141,2183,2184],{},"DORA Performance Tier Distribution: 2023 vs 2024",[1145,2186],{"width":1147,"height":1148,"fill":2187},"#1a1a2e",[1160,2189,2184],{"x":1162,"y":2190,"textAnchor":1164,"fill":2191,"fontSize":1166,"fontWeight":1167,"fontFamily":2192},"28","#e2e8f0","system-ui,sans-serif",[1145,2194],{"x":2195,"y":2196,"width":2197,"height":2197,"fill":2198,"rx":1192},"160","42","14","#94a3b8",[1160,2200,2202],{"x":1222,"y":2201,"fill":2191,"fontSize":1297,"fontFamily":2192},"53","2023",[1145,2204],{"x":2205,"y":2196,"width":2197,"height":2197,"fill":2191,"rx":1192},"225",[1160,2207,2209],{"x":2208,"y":2201,"fill":2191,"fontSize":1297,"fontFamily":2192},"243","2024",[1160,2211,2213],{"x":1180,"y":1200,"textAnchor":2212,"fill":2191,"fontSize":1174,"fontFamily":2192},"end","Elite",[1160,2215,2217],{"x":1180,"y":2216,"textAnchor":2212,"fill":2191,"fontSize":1174,"fontFamily":2192},"163","High",[1160,2219,2221],{"x":1180,"y":2220,"textAnchor":2212,"fill":2191,"fontSize":1174,"fontFamily":2192},"226","Medium",[1160,2223,2225],{"x":1180,"y":2224,"textAnchor":2212,"fill":2191,"fontSize":1174,"fontFamily":2192},"289","Low",[1245,2227],{"x1":1230,"y1":1230,"x2":1230,"y2":2228,"stroke":2229,"strokeWidth":1157},"310","#334155",[1245,2231],{"x1":1230,"y1":2228,"x2":2232,"y2":2228,"stroke":2229,"strokeWidth":1157},"540",[1245,2234],{"x1":2216,"y1":1230,"x2":2216,"y2":2228,"stroke":2229,"strokeWidth":1152,"strokeDashArray":2235},[2236,2236],"3",[1160,2238,2240],{"x":2216,"y":2239,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontFamily":2192},"316","20%",[1245,2242],{"x1":1237,"y1":1230,"x2":1237,"y2":2228,"stroke":2229,"strokeWidth":1152,"strokeDashArray":2243},[2236,2236],[1160,2245,2246],{"x":1237,"y":2239,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontFamily":2192},"40%",[1245,2248],{"x1":2249,"y1":1230,"x2":2249,"y2":2228,"stroke":2229,"strokeWidth":1152,"strokeDashArray":2250},"349",[2236,2236],[1160,2252,2253],{"x":2249,"y":2239,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontFamily":2192},"60%",[1245,2255],{"x1":2256,"y1":1230,"x2":2256,"y2":2228,"stroke":2229,"strokeWidth":1152,"strokeDashArray":2257},"442",[2236,2236],[1160,2259,2260],{"x":2256,"y":2239,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontFamily":2192},"80%",[1145,2262],{"x":1230,"y":2263,"width":2264,"height":2265,"fill":2198,"rx":1192},"76","83.7","16",[1160,2267,2269],{"x":2268,"y":1296,"fill":2198,"fontSize":1238,"fontFamily":2192,"dx":2236},"157.7","18%",[1145,2271],{"x":1230,"y":1223,"width":2272,"height":2265,"fill":2273,"rx":1192},"88.35","#22c55e",[1160,2275,2277],{"x":2276,"y":1234,"fill":2273,"fontSize":1238,"fontFamily":2192,"dx":2236},"162.35","19%",[1145,2279],{"x":1230,"y":1212,"width":2280,"height":2265,"fill":2198,"rx":1192},"144.15",[1160,2282,2285],{"x":2283,"y":2284,"fill":2198,"fontSize":1238,"fontFamily":2192,"dx":2236},"218.15","151","31%",[1145,2287],{"x":1230,"y":2288,"width":2289,"height":2265,"fill":2290,"rx":1192},"159","102.3","#3b82f6",[1160,2292,2295],{"x":2293,"y":2294,"fill":2290,"fontSize":1238,"fontFamily":2192,"dx":2236},"176.3","171","22%",[1145,2297],{"x":1230,"y":2298,"width":2299,"height":2265,"fill":2198,"rx":1192},"202","158.1",[1160,2301,2303],{"x":2302,"y":1312,"fill":2198,"fontSize":1238,"fontFamily":2192,"dx":2236},"232.1","34%",[1145,2305],{"x":1230,"y":2306,"width":2299,"height":2265,"fill":2307,"rx":1192},"222","#f59e0b",[1160,2309,2303],{"x":2302,"y":2310,"fill":2307,"fontSize":1238,"fontFamily":2192,"dx":2236},"234",[1145,2312],{"x":1230,"y":2313,"width":2314,"height":2265,"fill":2198,"rx":1192},"265","79.05",[1160,2316,2319],{"x":2317,"y":2318,"fill":2198,"fontSize":1238,"fontFamily":2192,"dx":2236},"153.05","277","17%",[1145,2321],{"x":1230,"y":2322,"width":2323,"height":2265,"fill":2324,"rx":1192},"285","116.25","#ef4444",[1160,2326,2329],{"x":2327,"y":2328,"fill":2324,"fontSize":1238,"fontFamily":2192,"dx":2236},"194.25","297","25%",[16,2331,2332],{},[145,2333,2334,2335,2339],{},"Source: ",[86,2336,2338],{"href":2174,"rel":2337},[90],"DORA 2024 State of DevOps Report"," via getdx.com. Gray bars = 2023; colored bars = 2024.",[16,2341,2342,2343,2348],{},"The absolute performance gap between tiers is where the numbers become difficult to dismiss. Elite performers deploy on demand with a lead time under one day, a 5% change failure rate, and recovery under one hour (",[86,2344,2347],{"href":2345,"rel":2346},"https:\u002F\u002Foctopus.com\u002Fdevops\u002Fmetrics\u002Fdora-metrics\u002F",[90],"DORA, via octopus.com, 2024","). Low performers deploy monthly to biannually, carry a 40-64% change failure rate, and need one week to one month to restore service.",[16,2350,2351],{},"The 2024 tier shift, where high performers collapsed into medium and low, suggests something specific. Teams who adopted CI\u002FCD tooling without adopting the branching and testing practices that make it effective are now showing up in the data. Buying a pipeline doesn't buy DORA elite status. The branching strategy is the forcing function.",[1134,2353,470,2357,470,2360,470,2363,470,470,2366,470,2368,470,2372,470,2375,470,470,470,2378,470,2381,470,2385,470,2388,470,470,2392,470,470,470,2396,470,2401,470,2403,470,470,2406,470,2410,470,2412,470,470,2416,470,2420,470,2422,470,2425,470,2429,470,2431,470,470,2433,470,2438,470,2440,470,2443,470,2448,470,2450,470,470,2453,470,2457,470,2459,470,2462,470,2466,470,2468,470,470,2471],{"viewBox":2354,"xmlns":1137,"role":267,"ariaLabel":2355,"style":2356},"0 0 580 300","Lollipop chart comparing DORA elite versus low performers on four metrics: deployment frequency (elite: on-demand vs low: monthly to biannual), lead time (elite: less than 1 day vs low: 1 to 6 months), change failure rate (elite: 5% vs low: 40 to 64%), and MTTR (elite: less than 1 hour vs low: 1 week to 1 month).","max-width:580px;width:100%;background:#0f172a;border-radius:8px;display:block;",[1141,2358,2359],{},"DORA Elite vs Low Performer Gap — Four Key Metrics",[1145,2361],{"width":1147,"height":1264,"fill":2362},"#0f172a",[1160,2364,2365],{"x":1162,"y":1163,"textAnchor":1164,"fill":2191,"fontSize":1166,"fontWeight":1167,"fontFamily":2192},"DORA Elite vs Low Performer Gap",[1271,2367],{"cx":1247,"cy":2196,"r":1184,"fill":2273},[1160,2369,2213],{"x":2370,"y":2371,"fill":2191,"fontSize":1297,"fontFamily":2192},"158","47",[1271,2373],{"cx":2374,"cy":2196,"r":1184,"fill":2324},"200",[1160,2376,2225],{"x":2377,"y":2371,"fill":2191,"fontSize":1297,"fontFamily":2192},"210",[1160,2379,2380],{"x":1238,"y":1200,"fill":2198,"fontSize":1297,"fontFamily":2192},"Deploy Freq",[1160,2382,2384],{"x":1238,"y":2383,"fill":2198,"fontSize":1297,"fontFamily":2192},"150","Lead Time",[1160,2386,2387],{"x":1238,"y":2374,"fill":2198,"fontSize":1297,"fontFamily":2192},"Failure Rate",[1160,2389,2391],{"x":1238,"y":2390,"fill":2198,"fontSize":1297,"fontFamily":2192},"250","MTTR",[1245,2393],{"x1":2394,"y1":1180,"x2":2394,"y2":2395,"stroke":2229,"strokeWidth":1157},"130","270",[1245,2397],{"x1":2394,"y1":2398,"x2":2399,"y2":2398,"stroke":2273,"strokeWidth":1192,"strokeDashArray":2400},"93","520",[1275,2236],[1271,2402],{"cx":2399,"cy":2398,"r":1158,"fill":2273},[1160,2404,2405],{"x":2399,"y":2398,"textAnchor":1164,"dominantBaseline":1164,"fill":2362,"fontSize":1158,"fontWeight":1298,"fontFamily":2192},"On-D",[1245,2407],{"x1":2394,"y1":2408,"x2":2374,"y2":2408,"stroke":2324,"strokeWidth":1192,"strokeDashArray":2409},"107",[1275,2236],[1271,2411],{"cx":2374,"cy":2408,"r":1158,"fill":2324},[1160,2413,2415],{"x":2374,"y":2408,"textAnchor":1164,"dominantBaseline":1164,"fill":2414,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},"#fff","Mo+",[1245,2417],{"x1":2394,"y1":1260,"x2":2418,"y2":1260,"stroke":2273,"strokeWidth":1192,"strokeDashArray":2419},"510",[1275,2236],[1271,2421],{"cx":2418,"cy":1260,"r":1158,"fill":2273},[1160,2423,2424],{"x":2418,"y":1260,"textAnchor":1164,"dominantBaseline":1164,"fill":2362,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},"\u003C1d",[1245,2426],{"x1":2394,"y1":2427,"x2":2377,"y2":2427,"stroke":2324,"strokeWidth":1192,"strokeDashArray":2428},"157",[1275,2236],[1271,2430],{"cx":2377,"cy":2427,"r":1158,"fill":2324},[1160,2432,2415],{"x":2377,"y":2427,"textAnchor":1164,"dominantBaseline":1164,"fill":2414,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},[1245,2434],{"x1":2394,"y1":2435,"x2":2436,"y2":2435,"stroke":2273,"strokeWidth":1192,"strokeDashArray":2437},"193","480",[1275,2236],[1271,2439],{"cx":2436,"cy":2435,"r":1158,"fill":2273},[1160,2441,2442],{"x":2436,"y":2435,"textAnchor":1164,"dominantBaseline":1164,"fill":2362,"fontSize":1158,"fontWeight":1298,"fontFamily":2192},"5%",[1245,2444],{"x1":2394,"y1":2445,"x2":2446,"y2":2445,"stroke":2324,"strokeWidth":1192,"strokeDashArray":2447},"207","220",[1275,2236],[1271,2449],{"cx":2446,"cy":2445,"r":1158,"fill":2324},[1160,2451,2452],{"x":2446,"y":2445,"textAnchor":1164,"dominantBaseline":1164,"fill":2414,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},"64%",[1245,2454],{"x1":2394,"y1":2208,"x2":2455,"y2":2208,"stroke":2273,"strokeWidth":1192,"strokeDashArray":2456},"515",[1275,2236],[1271,2458],{"cx":2455,"cy":2208,"r":1158,"fill":2273},[1160,2460,2461],{"x":2455,"y":2208,"textAnchor":1164,"dominantBaseline":1164,"fill":2362,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},"\u003C1h",[1245,2463],{"x1":2394,"y1":2464,"x2":1255,"y2":2464,"stroke":2324,"strokeWidth":1192,"strokeDashArray":2465},"257",[1275,2236],[1271,2467],{"cx":1255,"cy":2464,"r":1158,"fill":2324},[1160,2469,2470],{"x":1255,"y":2464,"textAnchor":1164,"dominantBaseline":1164,"fill":2414,"fontSize":1190,"fontWeight":1298,"fontFamily":2192},"Wks",[1160,2472,2475],{"x":1162,"y":2322,"textAnchor":1164,"fill":2473,"fontSize":2474,"fontFamily":2192},"#475569","9","Scale is qualitative — right = better performance. Labels show approximate values.",[16,2477,2478],{},[145,2479,2334,2480,2484,2485,2489],{},[86,2481,2483],{"href":2345,"rel":2482},[90],"DORA 2024 via octopus.com",". Elite performers who meet reliability targets are ",[86,2486,2488],{"href":1900,"rel":2487},[90],"2.3x more likely to use trunk-based development"," (DORA 2021).",[16,2491,2492],{},"The research doesn't fully prove causation from correlation. What is proven: elite performers who also hit reliability targets choose TBD at more than twice the rate of their peers. That's not a coincidence worth ignoring.",[51,2494],{},[54,2496,2498],{"id":2497},"the-decision-framework-which-strategy-fits-your-team","The Decision Framework: Which Strategy Fits Your Team?",[16,2500,2501],{},"Choosing between git branching strategies is only a hard decision if you don't have a rubric. This section gives you one: four dimensions, scored 0 to 2 each, so you get a number rather than a shrug. The matrix below compares strategies across six dimensions. The rubric below that tells you where your team lands today.",[1134,2503,470,2506,470,2509,470,470,2512,470,470,2516,470,2520,470,2526,470,2530,470,2534,470,2539,470,2544,470,2546,470,2549,470,2552,470,470,2556,470,2561,470,2565,470,2571,470,2575,470,2579,470,2582,470,2586,470,2589,470,2593,470,470,2596,470,2599,470,2602,470,2606,470,2610,470,2613,470,2615,470,2618,470,470,2620,470,2624,470,2628,470,2630,470,2632,470,2634,470,470,2636,470,2639,470,2643,470,2646,470,2649,470,2651,470,470,2655,470,2658,470,2662,470,2664,470,2666,470,2669,470,470,2673,470,2675,470,2679,470,2683,470,2687,470,2690,470,2693,470,470,2695,470,2698],{"viewBox":2504,"xmlns":1137,"role":267,"ariaLabel":2505,"style":2181},"0 0 580 340","Decision matrix table comparing four git branching strategies — Gitflow, GitHub Flow, GitLab Flow, and Trunk-Based Development — across six dimensions: team size fit, release model, CI\u002FCD maturity, feature flags, merge complexity, and creator endorsement for CD teams.",[1141,2507,2508],{},"Git Branching Strategy Decision Matrix",[1145,2510],{"width":1147,"height":2511,"fill":2187},"340",[1160,2513,2515],{"x":1162,"y":2514,"textAnchor":1164,"fill":2191,"fontSize":1174,"fontWeight":1298,"fontFamily":2192},"22","Strategy Decision Matrix",[1145,2517],{"x":1238,"y":2518,"width":1181,"height":2519,"fill":2362,"rx":2236},"30","24",[1145,2521],{"x":2522,"y":2518,"width":2523,"height":2519,"fill":2524,"rx":2236,"opacity":2525},"155","95","#7c3aed","0.7",[1145,2527],{"x":2528,"y":2518,"width":2523,"height":2519,"fill":2529,"rx":2236,"opacity":2525},"255","#0369a1",[1145,2531],{"x":2532,"y":2518,"width":2523,"height":2519,"fill":2533,"rx":2236,"opacity":2525},"355","#065f46",[1145,2535],{"x":2536,"y":2518,"width":2537,"height":2519,"fill":2538,"rx":2236,"opacity":2525},"455","115","#92400e",[1160,2540,2543],{"x":2541,"y":2542,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontWeight":1167,"fontFamily":2192},"80","46","Dimension",[1160,2545,2003],{"x":2298,"y":2542,"textAnchor":1164,"fill":2191,"fontSize":1238,"fontWeight":1167,"fontFamily":2192},[1160,2547,2054],{"x":2548,"y":2542,"textAnchor":1164,"fill":2191,"fontSize":1238,"fontWeight":1167,"fontFamily":2192},"302",[1160,2550,2085],{"x":2551,"y":2542,"textAnchor":1164,"fill":2191,"fontSize":1238,"fontWeight":1167,"fontFamily":2192},"402",[1160,2553,2555],{"x":2554,"y":2542,"textAnchor":1164,"fill":2191,"fontSize":1238,"fontWeight":1167,"fontFamily":2192},"512","Trunk-Based",[1145,2557],{"x":1238,"y":2558,"width":1147,"height":2196,"fill":2559,"rx":2560},"57","#1e293b","0",[1160,2562,2564],{"x":2541,"y":2563,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"73","Team Size Fit",[1160,2566,2570],{"x":2298,"y":2567,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},"69","#c4b5fd","8.5","Large,",[1160,2572,2574],{"x":2298,"y":2573,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},"82","distributed",[1160,2576,2578],{"x":2548,"y":2567,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},"#93c5fd","5-30",[1160,2580,2581],{"x":2548,"y":2573,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},"engineers",[1160,2583,2585],{"x":2551,"y":2567,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},"#6ee7b7","Medium-large,",[1160,2587,2588],{"x":2551,"y":2573,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},"multi-env",[1160,2590,2592],{"x":2554,"y":2567,"textAnchor":1164,"fill":2591,"fontSize":2569,"fontFamily":2192},"#fcd34d","Any, if",[1160,2594,2595],{"x":2554,"y":2573,"textAnchor":1164,"fill":2591,"fontSize":2569,"fontFamily":2192},"experienced",[1145,2597],{"x":1238,"y":2598,"width":1147,"height":2196,"fill":2362,"rx":2560},"99",[1160,2600,2601],{"x":2541,"y":2537,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"Release Model",[1160,2603,2605],{"x":2298,"y":2604,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},"111","Scheduled,",[1160,2607,2609],{"x":2298,"y":2608,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},"124","versioned",[1160,2611,2612],{"x":2548,"y":2537,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},"Continuous",[1160,2614,2612],{"x":2551,"y":2604,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},[1160,2616,2617],{"x":2551,"y":2608,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},"+ staged",[1160,2619,2612],{"x":2554,"y":2537,"textAnchor":1164,"fill":2591,"fontSize":2569,"fontFamily":2192},[1145,2621],{"x":1238,"y":2622,"width":1147,"height":2623,"fill":2559,"rx":2560},"141","34",[1160,2625,2627],{"x":2541,"y":2626,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"162","CI\u002FCD Maturity",[1160,2629,2225],{"x":2298,"y":2626,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},[1160,2631,2221],{"x":2548,"y":2626,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},[1160,2633,2221],{"x":2551,"y":2626,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},[1160,2635,2217],{"x":2554,"y":2626,"textAnchor":1164,"fill":2591,"fontSize":2569,"fontFamily":2192},[1145,2637],{"x":1238,"y":2638,"width":1147,"height":2623,"fill":2362,"rx":2560},"175",[1160,2640,2642],{"x":2541,"y":2641,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"196","Feature Flags",[1160,2644,2645],{"x":2298,"y":2641,"textAnchor":1164,"fill":2568,"fontSize":2569,"fontFamily":2192},"No",[1160,2647,2648],{"x":2548,"y":2641,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},"Recommended",[1160,2650,2648],{"x":2551,"y":2641,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},[1160,2652,2654],{"x":2554,"y":2641,"textAnchor":1164,"fill":2653,"fontSize":2569,"fontWeight":1298,"fontFamily":2192},"#f87171","Required",[1145,2656],{"x":1238,"y":2657,"width":1147,"height":2623,"fill":2559,"rx":2560},"209",[1160,2659,2661],{"x":2541,"y":2660,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"230","Merge Complexity",[1160,2663,2217],{"x":2298,"y":2660,"textAnchor":1164,"fill":2653,"fontSize":2569,"fontFamily":2192},[1160,2665,2225],{"x":2548,"y":2660,"textAnchor":1164,"fill":2577,"fontSize":2569,"fontFamily":2192},[1160,2667,2668],{"x":2551,"y":2660,"textAnchor":1164,"fill":2584,"fontSize":2569,"fontFamily":2192},"Low-Medium",[1160,2670,2672],{"x":2554,"y":2660,"textAnchor":1164,"fill":2671,"fontSize":2569,"fontWeight":1298,"fontFamily":2192},"#4ade80","Very Low",[1145,2674],{"x":1238,"y":2208,"width":1147,"height":1187,"fill":2362,"rx":2560},[1160,2676,2678],{"x":2541,"y":2677,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"260","Creator Endorses",[1160,2680,2682],{"x":2541,"y":2681,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"273","for CD Teams?",[1160,2684,2686],{"x":2298,"y":2685,"textAnchor":1164,"fill":2653,"fontSize":2569,"fontWeight":1298,"fontFamily":2192},"271","No (retracted)",[1160,2688,2689],{"x":2548,"y":2685,"textAnchor":1164,"fill":2671,"fontSize":2569,"fontWeight":1298,"fontFamily":2192},"Yes",[1160,2691,2692],{"x":2551,"y":2685,"textAnchor":1164,"fill":2198,"fontSize":2569,"fontFamily":2192},"N\u002FA",[1160,2694,2689],{"x":2554,"y":2685,"textAnchor":1164,"fill":2671,"fontSize":2569,"fontWeight":1298,"fontFamily":2192},[1145,2696],{"x":1238,"y":2697,"width":1147,"height":1192,"fill":2229},"293",[1160,2699,2700],{"x":1162,"y":1148,"textAnchor":1164,"fill":2473,"fontSize":2474,"fontFamily":2192},"Sources: nvie.com (2020), dora.dev, thoughtworks.com\u002Fradar, AWS Prescriptive Guidance",[16,2702,2703],{},[145,2704,2705,2706,399,2710,399,2714,399,2718,339],{},"Strategy comparison across six dimensions. Data sources: ",[86,2707,2709],{"href":260,"rel":2708},[90],"nvie.com",[86,2711,2713],{"href":768,"rel":2712},[90],"dora.dev",[86,2715,2717],{"href":2047,"rel":2716},[90],"ThoughtWorks Radar",[86,2719,2029],{"href":2027,"rel":2720},[90],[230,2722,2724],{"id":2723},"team-readiness-rubric","Team Readiness Rubric",[16,2726,2727],{},"Score your team on these four dimensions. Each scores 0, 1, or 2.",[16,2729,2730],{},[31,2731,2732],{},"1. CI\u002FCD Maturity",[35,2734,2735,2738,2741],{},[38,2736,2737],{},"0: No pipeline, or deployments triggered manually by an individual",[38,2739,2740],{},"1: Basic pipeline. Automated tests run on every commit, but deploys require a manual approval step",[38,2742,2743],{},"2: Deploy-on-merge to production with automated rollback. No human in the deployment path",[16,2745,2746],{},[31,2747,2748],{},"2. Test Coverage",[35,2750,2751,2754,2757],{},[38,2752,2753],{},"0: Below 50% line coverage, or coverage not measured",[38,2755,2756],{},"1: 50-80% line coverage with a meaningful integration suite",[38,2758,2759],{},"2: Above 80% line coverage, plus mutation testing (e.g., mutation score above 60% in Stryker or PITest). You know your tests catch regressions, not just execute lines",[16,2761,2762],{},[31,2763,2764],{},"3. Feature Flag Infrastructure",[35,2766,2767,2770,2773],{},[38,2768,2769],{},"0: No flags. Toggles baked into code as environment variables or comments",[38,2771,2772],{},"1: Ad hoc flags with no central management or audit trail. Flags accumulate silently",[38,2774,2775],{},"2: Managed flag platform (LaunchDarkly, Unleash, or any OpenFeature-compliant tool) with flag lifecycle tracking and expiry dates enforced in tickets",[16,2777,2778],{},[31,2779,2780],{},"4. Developer Experience",[35,2782,2783,2786,2789],{},[38,2784,2785],{},"0: Mixed or primarily junior engineers. No exposure to trunk-based or continuous delivery workflows",[38,2787,2788],{},"1: Mostly mid-level engineers. Comfortable with PR reviews and basic CI, but branches routinely exceed 3 days",[38,2790,2791],{},"2: Mostly senior engineers with production TBD or continuous delivery experience. They instinctively write small, focused commits",[16,2793,2794],{},[31,2795,2796],{},"Your score:",[35,2798,2799,2805,2811],{},[38,2800,2801,2804],{},[31,2802,2803],{},"0–3:"," Start with Gitflow (for scheduled releases) or GitHub Flow (for continuous delivery aspirations).",[38,2806,2807,2810],{},[31,2808,2809],{},"4–5:"," GitHub Flow or GitLab Flow. Build the infrastructure for a future migration.",[38,2812,2813,2816],{},[31,2814,2815],{},"6–8:"," You're ready for trunk-based development. The bottleneck is now cultural, not technical.",[16,2818,2819],{},"Teams that score a 5 and migrate directly to TBD typically regress. The missing point is almost always feature flag infrastructure, which only reveals its absence when a half-finished feature ships on a Friday.",[51,2821],{},[54,2823,2825],{"id":2824},"the-feature-flag-connection","The Feature Flag Connection",[16,2827,2828,2829,2834],{},"Feature flags aren't a nice-to-have for trunk-based development. They're structurally required. TBD means incomplete features live in production code, and feature flags are what prevents those features from being visible to users before they're ready. Without that infrastructure, every TBD commit is a gamble. The ",[86,2830,2833],{"href":2831,"rel":2832},"https:\u002F\u002Flaunchdarkly.com\u002Fblog\u002F2024-survey-impact-of-feature-management\u002F",[90],"2024 LaunchDarkly\u002FWakefield Research survey"," (n=500, April-May 2024) found that 59% of feature flag users deploy multiple times per week, versus 32% of non-users. On-demand deployment: 20% of flag users versus 3% of non-users.",[16,2836,2837],{},"LaunchDarkly commissioned this survey, which warrants scrutiny on the specific numbers. The underlying signal, that structured feature flag management correlates with higher deployment frequency, is consistent with DORA findings. Treat the percentages as vendor-favorable. Treat the pattern as real.",[16,2839,2840],{},"Here's the distinction most articles skip: deployment and release are not the same event. Deployment means code reaches production. Release means the feature becomes visible to users. TBD separates these two events deliberately. A flag gates the release. The deployment happens continuously regardless.",[16,2842,2843],{},"Progressive rollout uses this separation systematically. 0% of users see the feature, then 5%, 25%, 50%, 100%, with observability at each stage to catch regressions before they reach your full user base.",[16,2845,2846,2847,2852],{},"Flag debt is the predictable failure mode. Every flag deployed without a removal date becomes permanent infrastructure. The discipline is simple: every flag gets an expiry date in the ticket that creates it. ",[86,2848,2851],{"href":2849,"rel":2850},"https:\u002F\u002Fopenfeature.dev",[90],"OpenFeature",", a CNCF project, provides a vendor-agnostic feature flag API. ThoughtWorks Technology Radar lists it as worth watching for teams evaluating flag infrastructure without locking into a single vendor.",[26,2854,2855],{},[16,2856,2857,84,2859,2863],{},[31,2858,116],{},[86,2860,2862],{"href":2861},"\u002Fblog\u002Ffeature-flag-platform-guide","Building a Feature Flag Platform",". Choosing between LaunchDarkly, Unleash, and self-hosted OpenFeature.",[1134,2865,470,2869,470,2872,470,2875,470,470,2878,470,2881,470,2884,470,2887,470,470,2890,470,2893,470,470,2895,470,2897,470,2901,470,2904,470,2907,470,2909,470,2912,470,2914,470,2916,470,2919,470,470,2923,470,2928,470,2932,470,2936,470,2939,470,2944,470,470,2948,470,2952,470,2955,470,2960,470,2963,470,2967,470,470,2970,470,2974,470,2978,470,2981,470,2984,470,2987],{"viewBox":2866,"xmlns":1137,"role":267,"ariaLabel":2867,"style":2868},"0 0 560 260","Grouped bar chart showing feature management impact on deployment velocity. Compares feature flag users versus non-users on three metrics: deploy multiple times per week (59% vs 32%), deploy on-demand (20% vs 3%), and recover within one day (86% vs 59%).","max-width:560px;width:100%;background:#0f172a;border-radius:8px;display:block;",[1141,2870,2871],{},"Feature Management Impact on Deployment Velocity",[1145,2873],{"width":2874,"height":2677,"fill":2362},"560",[1160,2876,2871],{"x":2877,"y":2514,"textAnchor":1164,"fill":2191,"fontSize":1174,"fontWeight":1298,"fontFamily":2192},"280",[1145,2879],{"x":2880,"y":1179,"width":2197,"height":1174,"fill":2273,"rx":1192},"120",[1160,2882,2883],{"x":1316,"y":2371,"fill":2191,"fontSize":1238,"fontFamily":2192},"Flag users",[1145,2885],{"x":2205,"y":1179,"width":2197,"height":1174,"fill":2886,"rx":1192},"#64748b",[1160,2888,2889],{"x":2208,"y":2371,"fill":2191,"fontSize":1238,"fontFamily":2192},"Non-users",[1245,2891],{"x1":1180,"y1":2892,"x2":1180,"y2":2446,"stroke":2229,"strokeWidth":1157},"55",[1245,2894],{"x1":1180,"y1":2446,"x2":2232,"y2":2446,"stroke":2229,"strokeWidth":1157},[1245,2896],{"x1":1180,"y1":2892,"x2":2232,"y2":2892,"stroke":2559,"strokeWidth":1157},[1160,2898,2900],{"x":2892,"y":2899,"textAnchor":2212,"fill":2886,"fontSize":2474,"fontFamily":2192},"59","100%",[1245,2902],{"x1":1180,"y1":2903,"x2":2232,"y2":2903,"stroke":2559,"strokeWidth":1157},"89",[1160,2905,2906],{"x":2892,"y":2398,"textAnchor":2212,"fill":2886,"fontSize":2474,"fontFamily":2192},"75%",[1245,2908],{"x1":1180,"y1":1286,"x2":2232,"y2":1286,"stroke":2559,"strokeWidth":1157},[1160,2910,2911],{"x":2892,"y":1208,"textAnchor":2212,"fill":2886,"fontSize":2474,"fontFamily":2192},"50%",[1245,2913],{"x1":1180,"y1":2522,"x2":2232,"y2":2522,"stroke":2559,"strokeWidth":1157},[1160,2915,2329],{"x":2892,"y":2288,"textAnchor":2212,"fill":2886,"fontSize":2474,"fontFamily":2192},[1245,2917],{"x1":1180,"y1":2918,"x2":2232,"y2":2918,"stroke":2559,"strokeWidth":1157},"188",[1160,2920,2922],{"x":2892,"y":2921,"textAnchor":2212,"fill":2886,"fontSize":2474,"fontFamily":2192},"192","0%",[1145,2924],{"x":2925,"y":2926,"width":1187,"height":2927,"fill":2273,"rx":2236},"90","123","97",[1160,2929,2931],{"x":2537,"y":2930,"textAnchor":1164,"fill":2273,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"118","59%",[1145,2933],{"x":2934,"y":2935,"width":1187,"height":2201,"fill":2886,"rx":2236},"145","167",[1160,2937,2938],{"x":1302,"y":2626,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"32%",[1160,2940,2943],{"x":2941,"y":2942,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"142","240","Deploy",[1160,2945,2947],{"x":2941,"y":2946,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"252","multiple\u002Fwk",[1145,2949],{"x":2942,"y":2950,"width":1187,"height":2951,"fill":2273,"rx":2236},"187","33",[1160,2953,2240],{"x":2313,"y":2954,"textAnchor":1164,"fill":2273,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"182",[1145,2956],{"x":2957,"y":2958,"width":1187,"height":2959,"fill":2886,"rx":1192},"295","215","5",[1160,2961,2962],{"x":1148,"y":2377,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"3%",[1160,2964,2966],{"x":2965,"y":2942,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"292","On-demand",[1160,2968,2969],{"x":2965,"y":2946,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"deploy",[1145,2971],{"x":2972,"y":2973,"width":1187,"height":2622,"fill":2273,"rx":2236},"390","79",[1160,2975,2977],{"x":2976,"y":1188,"textAnchor":1164,"fill":2273,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"415","86%",[1145,2979],{"x":2980,"y":2926,"width":1187,"height":2927,"fill":2886,"rx":2236},"445",[1160,2982,2931],{"x":2983,"y":2930,"textAnchor":1164,"fill":2198,"fontSize":1238,"fontWeight":1298,"fontFamily":2192},"470",[1160,2985,2986],{"x":2256,"y":2942,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"Recover",[1160,2988,2989],{"x":2256,"y":2946,"textAnchor":1164,"fill":2198,"fontSize":2474,"fontFamily":2192},"within 1 day",[16,2991,2992],{},[145,2993,2334,2994,2998],{},[86,2995,2997],{"href":2831,"rel":2996},[90],"LaunchDarkly\u002FWakefield Research survey",", n=500, April–May 2024. LaunchDarkly commissioned this research; treat magnitudes as vendor-favorable, trend as consistent with DORA findings.",[51,3000],{},[54,3002,3004],{"id":3003},"migration-path-moving-between-strategies","Migration Path: Moving Between Strategies",[16,3006,3007],{},"Most teams don't start from scratch. They migrate. The failure mode is attempting a big-bang switch: announce the new strategy on Monday, wonder why PRs are still sitting open on Friday. Migration works in incremental steps, with each step de-risking the next.",[230,3009,3011],{"id":3010},"gitflow-to-github-flow","Gitflow to GitHub Flow",[16,3013,3014,3017],{},[31,3015,3016],{},"Step 1:"," Eliminate the develop branch. Merge its current state to main. From this point forward, feature branches target main directly. Expect initial discomfort as engineers lose the \"safety net\" of develop.",[16,3019,3020,3023],{},[31,3021,3022],{},"Step 2:"," Shorten feature branch lifetimes to less than one sprint. Any branch approaching sprint length gets split into smaller units of work.",[16,3025,3026,3029],{},[31,3027,3028],{},"Step 3:"," Add a deploy-on-merge pipeline. This is the structural change. Merging to main triggers a deployment, not a scheduled release process.",[16,3031,3032,3035],{},[31,3033,3034],{},"Step 4:"," Introduce feature flags for any in-progress work. Features that aren't user-ready but are code-complete can now merge safely behind a flag.",[230,3037,3039],{"id":3038},"github-flow-to-trunk-based-development","GitHub Flow to Trunk-Based Development",[16,3041,3042,3044],{},[31,3043,3016],{}," Reduce branch lifetimes from days to hours. This is a cultural shift as much as a technical one. Enforce it through PR aging metrics in your dashboard.",[16,3046,3047,3049],{},[31,3048,3022],{}," Increase merge frequency to at least once daily. Engineers who haven't merged by end-of-day should have a small branch ready to merge or a continuation planned for tomorrow.",[16,3051,3052,3054],{},[31,3053,3028],{}," Establish a full feature flag platform before this step, not after. This is where teams most frequently skip ahead and regret it.",[16,3056,3057,3059],{},[31,3058,3034],{}," Raise test coverage above 80% with confidence in the suite's quality. Coverage alone isn't sufficient. A suite with no mutation testing can hit 80% and still miss critical paths.",[16,3061,3062,3065],{},[31,3063,3064],{},"Step 5:"," Eliminate code freezes and integration phases completely. If your calendar still has a \"code freeze\" event, you haven't completed the migration.",[26,3067,3068],{},[16,3069,3070,3073],{},[31,3071,3072],{},"Regulated industry note."," Healthcare, finance, and gambling teams successfully run trunk-based development in production. The compliance requirement is auditability, not branch-based release gates. GitLab Flow's environment branches satisfy the same audit need: every promotion is a traceable merge event, reviewable by auditors, without Gitflow's branch management overhead. The assumption that regulated industries require Gitflow is a legacy of pre-CI\u002FCD compliance frameworks.",[51,3075],{},[54,3077,722],{"id":721},[230,3079,3081],{"id":3080},"whats-the-difference-between-github-flow-and-trunk-based-development","What's the difference between GitHub Flow and trunk-based development?",[16,3083,3084,3085,3088],{},"GitHub Flow uses short-lived branches (typically days) merged to main via pull request. Trunk-based development uses branches measured in hours, with at least one daily merge, and stricter limits: ",[86,3086,2130],{"href":768,"rel":3087},[90]," as three or fewer active branches. Both deploy continuously; TBD has more explicit constraints on branch lifetime and count.",[230,3090,3092],{"id":3091},"can-regulated-industries-healthcare-finance-use-trunk-based-development","Can regulated industries (healthcare, finance) use trunk-based development?",[16,3094,3095],{},"Yes. Compliance requires an audit trail, not a specific branching model. GitLab Flow's downstream-only merge rule creates a traceable promotion history that satisfies SOC 2 and PCI DSS audit requirements. TBD with GitLab Flow's environment branches is both continuous and auditable. The two aren't mutually exclusive.",[230,3097,3099],{"id":3098},"is-gitflow-dead","Is Gitflow dead?",[16,3101,3102,3103,3107,3108,3112],{},"Not dead, but retired from continuous delivery contexts. Its creator ",[86,3104,3106],{"href":260,"rel":3105},[90],"recommended against it for CD teams in 2020",". ThoughtWorks placed feature branching in ",[86,3109,3111],{"href":2047,"rel":3110},[90],"\"Hold\"",". Gitflow remains appropriate for versioned software, embedded systems, and libraries with multiple supported release lines that can't adopt continuous deployment.",[230,3114,3116],{"id":3115},"how-does-branching-strategy-affect-cicd-pipeline-performance","How does branching strategy affect CI\u002FCD pipeline performance?",[16,3118,3119,3120,3124],{},"Longer-lived branches accumulate integration debt: code that hasn't been tested against the current state of main. ",[86,3121,3123],{"href":1900,"rel":3122},[90],"DORA 2021 research"," found elite performers are 2.3x more likely to use trunk-based development. The mechanism: frequent small merges reduce the blast radius of each integration, allowing pipelines to run faster with smaller change sets.",[230,3126,3128],{"id":3127},"what-is-gitlab-flow-and-when-should-i-use-it-instead-of-github-flow","What is GitLab Flow, and when should I use it instead of GitHub Flow?",[16,3130,3131],{},"GitLab Flow adds environment branches (main, staging, production) to GitHub Flow's simplicity, with a downstream-only merge rule: code always promotes forward, never committed directly to staging or production. Choose it over GitHub Flow when you have mandatory pre-production sign-off, multiple deployment environments, or audit requirements for deployment traceability.",[51,3133],{},[16,3135,3136],{},"Run the readiness rubric with your team in your next retro. If you score below 4, the bottleneck is infrastructure, not will. If you score 6 or above, the migration to trunk-based development is waiting on a decision, not a missing capability.",[16,3138,3139],{},"The data gives you the rationale to take to your team or your leadership: 2.3x TBD correlation with elite DORA performance, 182x deployment frequency gap, 26x bug rate from manual merge conflicts. The rubric gives you the honest starting point. The migration steps give you the path. What most teams skip is the feature flag platform at step 3. Don't.",[26,3141,3142],{},[16,3143,3144,84,3146,3150],{},[31,3145,116],{},[86,3147,3149],{"href":3148},"\u002Fblog\u002Fdora-metrics-guide","DORA Metrics Implementation Guide",". How to measure and track your four key DevOps performance indicators.",[840,3152,3153],{"type":842},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"FAQPage\",\n  \"mainEntity\": [\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What's the difference between GitHub Flow and trunk-based development?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"GitHub Flow uses short-lived branches (typically days) merged to main via pull request. Trunk-based development uses branches measured in hours, with at least one daily merge, and stricter limits: DORA defines TBD as three or fewer active branches. Both deploy continuously; TBD has more explicit constraints on branch lifetime and count.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Can regulated industries (healthcare, finance) use trunk-based development?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Yes. Compliance requires an audit trail, not a specific branching model. GitLab Flow's downstream-only merge rule creates a traceable promotion history that satisfies SOC 2 and PCI DSS audit requirements. TBD with GitLab Flow's environment branches is both continuous and auditable.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"Is Gitflow dead?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Not dead, but retired from continuous delivery contexts. Its creator recommended against it for CD teams in 2020. ThoughtWorks placed feature branching in Hold. Gitflow remains appropriate for versioned software, embedded systems, and libraries with multiple supported release lines that can't adopt continuous deployment.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"How does branching strategy affect CI\u002FCD pipeline performance?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"Longer-lived branches accumulate integration debt: code that hasn't been tested against the current state of main. DORA 2021 research found elite performers are 2.3x more likely to use trunk-based development. The mechanism: frequent small merges reduce the blast radius of each integration, allowing pipelines to run faster with smaller change sets.\"\n      }\n    },\n    {\n      \"@type\": \"Question\",\n      \"name\": \"What is GitLab Flow, and when should I use it instead of GitHub Flow?\",\n      \"acceptedAnswer\": {\n        \"@type\": \"Answer\",\n        \"text\": \"GitLab Flow adds environment branches (main, staging, production) to GitHub Flow's simplicity, with a downstream-only merge rule: code always promotes forward, never committed directly to staging or production. Choose it over GitHub Flow when you have mandatory pre-production sign-off, multiple deployment environments, or audit requirements for deployment traceability.\"\n      }\n    }\n  ]\n}\n",{"title":845,"searchDepth":846,"depth":846,"links":3155},[3156,3157,3163,3164,3167,3168,3172],{"id":1944,"depth":849,"text":1945},{"id":1998,"depth":849,"text":1999,"children":3158},[3159,3160,3161,3162],{"id":2002,"depth":846,"text":2003},{"id":2053,"depth":846,"text":2054},{"id":2084,"depth":846,"text":2085},{"id":2109,"depth":846,"text":2110},{"id":2159,"depth":849,"text":2160},{"id":2497,"depth":849,"text":2498,"children":3165},[3166],{"id":2723,"depth":846,"text":2724},{"id":2824,"depth":849,"text":2825},{"id":3003,"depth":849,"text":3004,"children":3169},[3170,3171],{"id":3010,"depth":846,"text":3011},{"id":3038,"depth":846,"text":3039},{"id":721,"depth":849,"text":722,"children":3173},[3174,3175,3176,3177,3178],{"id":3080,"depth":846,"text":3081},{"id":3091,"depth":846,"text":3092},{"id":3098,"depth":846,"text":3099},{"id":3115,"depth":846,"text":3116},{"id":3127,"depth":846,"text":3128},"2026-05-27","Compare GitHub Flow, trunk-based development, Gitflow, and GitLab Flow using DORA benchmarks and a team-readiness rubric. Choose by evidence, not convention.",{},"\u002Fgit-branching-strategies",{"title":1883,"description":3180},"git-branching-strategies\u002Findex",[3186,888,889,2109,892,3187],"git","engineering-leadership","kSFZKDuAZDpQGswrBlewAo3NIqfLI8zf6wgmmd7rx2M",1782645815295]