Skip to content
academia.sh

Lesson 17 / 19

Governance Model

Modeling centralized, federated, and hybrid governance over demand and capacity, queue time turning into local copies, the tipping point that shifts with scale, and separating decisions that must stay centralized.

Contents

The previous lesson’s state machine did not ask one thing: who does the review? Having all three approvals come from a single central team produces a different system than having approvals come from within the contributing teams themselves.

The governance model is the answer to this question, and it is a choice between two quantities: consistency and speed. If a single team reviews everything, decisions are consistent but the queue grows; if every team reviews itself, the queue shortens but decisions scatter. This lesson measures the trade-off with a model and shows that the choice depends on scale.

Three Models

Centralized governance. The system has a single owning team. Component design, review, and release all pass through this team. Product teams propose contributions, but the decision is central. Capacity is bounded by this team’s size and does not grow as the organization grows.

Federated governance. The system’s components are distributed among the product teams. Each team reviews and releases the components it owns internally. Capacity grows together with team count. But the reviewer only sees their own product; they do not know how the same decision was made in another product.

Hybrid governance. A core team holds the token layer, the naming convention, and breaking-change approval; drafting and the first review happen inside the product teams. Capacity depends on both the product teams’ preparation capacity and the core’s approval capacity — whichever is smaller sets the bound.

What separates these three models is how much of the contributions are reviewed with an eye that sees the whole system. The model below takes this ratio directly as a variable and computes the deviation count from it.

Building the Model

The model tracks three things: demand arriving per period, the model’s capacity, and the work accumulating in the queue. When the queue exceeds a certain duration, a contribution is abandoned and that team writes its own copy; this copy is a deviation. The second source of deviation is reviews carried out without system-wide visibility.

// governance.mjs — comparing three governance models by queue time and deviation count

// Assumptions (all taken as this organization's measured values):
const PERIOD = 12;                  // how many periods to track
const DEMAND_PER_TEAM = 5;          // contribution demand a product team produces per period
const WAIT_THRESHOLD = 2;           // work waiting longer than this many periods is abandoned
const BASE_DEVIATION_RATE = 0.35;   // probability that a contribution reviewed without system-wide visibility deviates

// Models. "capacity" gives the number of contributions completable in one period;
// "visibility" gives how much of the contributions are reviewed with an eye that
// sees the whole system.
const MODELS = [
  {
    name: "centralized",
    capacity: () => 22,               // single team; independent of team count
    visibility: 0.95,
  },
  {
    name: "federated",
    capacity: (team) => 6 * team,     // each product team runs its own review
    visibility: 0.15,                 // spot-check review only
  },
  {
    name: "hybrid",
    capacity: (team) => Math.min(55, 6 * team), // product team prepares, core approves
    visibility: 0.70,
  },
];

function run(capacity, visibility, demand) {
  let queue = 0, accepted = 0, localCopy = 0, queueTotal = 0;
  for (let d = 0; d < PERIOD; d++) {
    queue += demand;
    const processed = Math.min(queue, capacity);
    queue -= processed;
    accepted += processed;
    const ceiling = WAIT_THRESHOLD * capacity;
    if (queue > ceiling) {
      localCopy += queue - ceiling;
      queue = ceiling;
    }
    queueTotal += queue;
  }
  const avgQueue = queueTotal / PERIOD;
  return {
    accepted,
    localCopy,
    wait: avgQueue / capacity,
    reviewDeviation: accepted * BASE_DEVIATION_RATE * (1 - visibility),
    finalQueue: queue,
  };
}

for (const team of [4, 12]) {
  const demand = DEMAND_PER_TEAM * team;
  console.log(`\n=== ${team} product teams · ${demand} contributions demanded per period · ${PERIOD} periods · total demand ${demand * PERIOD} ===`);
  console.log("model         capacity   accepted     pending    wait(periods)   review deviation   local copy   total deviation");
  const rows = [];
  for (const m of MODELS) {
    const cap = m.capacity(team);
    const s = run(cap, m.visibility, demand);
    const total = s.reviewDeviation + s.localCopy;
    rows.push({ name: m.name, total });
    console.log(
      `${m.name.padEnd(13)} ${String(cap).padStart(8)} ${String(s.accepted).padStart(10)} ${String(s.finalQueue).padStart(10)} ` +
      `${s.wait.toFixed(2).padStart(15)} ${s.reviewDeviation.toFixed(1).padStart(19)} ` +
      `${String(s.localCopy).padStart(13)} ${total.toFixed(1).padStart(16)}`
    );
  }
  rows.sort((a, b) => a.total - b.total);
  console.log(`model producing least deviation: ${rows[0].name} (${rows[0].total.toFixed(1)})`);
}

// Tipping point: up to how many product teams does the centralized model keep up
// without building a queue?
console.log("\nteams   demand   centralized capacity   builds a queue");
for (let team = 2; team <= 8; team++) {
  const demand = DEMAND_PER_TEAM * team;
  const cap = MODELS[0].capacity(team);
  console.log(`${String(team).padStart(5)} ${String(demand).padStart(8)} ${String(cap).padStart(21)} ${(demand > cap ? "yes" : "no").padStart(16)}`);
}

// How much the core's approval capacity changes the outcome in the hybrid model.
console.log("\ncore approval capacity in the hybrid model (12 teams, demand 60, total demand 720)");
console.log("core   effective capacity   accepted     pending   local copy   total deviation");
for (const core of [35, 45, 55, 65]) {
  const cap = Math.min(core, 6 * 12);
  const s = run(cap, 0.70, 60);
  console.log(
    `${String(core).padStart(4)} ${String(cap).padStart(19)} ${String(s.accepted).padStart(10)} ` +
    `${String(s.finalQueue).padStart(10)} ${String(s.localCopy).padStart(13)} ` +
    `${(s.reviewDeviation + s.localCopy).toFixed(1).padStart(17)}`
  );
}
=== 4 product teams · 20 contributions demanded per period · 12 periods · total demand 240 ===
model         capacity   accepted     pending    wait(periods)   review deviation   local copy   total deviation
centralized         22        240          0            0.00                 4.2             0              4.2
federated           24        240          0            0.00                71.4             0             71.4
hybrid              24        240          0            0.00                25.2             0             25.2
model producing least deviation: centralized (4.2)

=== 12 product teams · 60 contributions demanded per period · 12 periods · total demand 720 ===
model         capacity   accepted     pending    wait(periods)   review deviation   local copy   total deviation
centralized         22        264         44            1.98                 4.6           412            416.6
federated           72        720          0            0.00               214.2             0            214.2
hybrid              55        660         60            0.59                69.3             0             69.3
model producing least deviation: hybrid (69.3)

teams   demand   centralized capacity   builds a queue
    2       10                    22               no
    3       15                    22               no
    4       20                    22               no
    5       25                    22              yes
    6       30                    22              yes
    7       35                    22              yes
    8       40                    22              yes

core approval capacity in the hybrid model (12 teams, demand 60, total demand 720)
core   effective capacity   accepted     pending   local copy   total deviation
  35                  35        420         70           230             274.1
  45                  45        540         90            90             146.7
  55                  55        660         60             0              69.3
  65                  65        720          0             0              75.6

The Outcome Changing with Scale

The two tables run the same three models at two different scales, and the ranking reverses.

At four product teams, the centralized model gives the best result: all 240 contributions ship, there is no wait, and deviation is 4.2. The federated model does the same work in the same time, but its deviation is 71.4 — seventeen times higher. At this scale, the central team’s capacity is enough to meet demand; the federated model’s extra capacity buys nothing, only paying the cost of lower review visibility.

At twelve product teams, the centralized model collapses: deviation is 416.6. 412 of that number is local copies. The central team can only handle 264 of the 720 demanded; the rest sits in the queue past the wait threshold and teams write their own copies.

This mechanism is the point most governance discussions miss: the centralized model’s cost is not the wait itself but the wait turning into abandonment. The central team’s review quality has not dropped at all — its deviation rate is still 4.6, the lowest value. The system stays good at what it reviews; the problem is that it is not reviewing most of the work.

The third table gives the centralized model’s tipping point: no queue builds up to four product teams, and one starts from the fifth on. This number is not a rule but the ratio of this organization’s capacity to its demand — enlarge the central team and the point shifts right. What decides is not the model’s name but this ratio.

Tuning the Hybrid Model

The last table shows how sensitive the hybrid model is to a single parameter — the core’s approval capacity — and it needs to be read carefully.

At a core capacity of 35, the hybrid model is nearly as bad as the centralized one: 230 local copies. At capacity 45, local copies drop to 90; at 55, to zero. The hybrid model working, in other words, depends on the core approving fast enough to keep up with the product teams’ preparation speed. If the core becomes the bottleneck, a model named hybrid is a centralized model in disguise.

The last row holds a trap: at core capacity 65, total deviation rises to 75.6 — higher than 69.3 at 55. This does not mean raising capacity is harmful. At 55, 660 contributions have shipped and 60 still sit in the queue; at 65, all 720 have shipped. Deviation per shipped contribution is the same in both cases — 69.3 over 660 and 75.6 over 720 both equal 0.105. The total looks lower only because part of the work had not been done yet.

This is a general flaw to avoid when building a measurement: unmet demand can look like a success. Unless the number of contributions shipped and the length of the pending queue are reported, a system that does no work produces the cleanest-looking numbers.

Decisions That Must Stay Centralized

Model choice is not a single switch; each type of decision can be kept centralized or distributed on its own. The criterion for the split is how many components a decision affects at once.

Decisions that must stay centralized are the ones whose effect reaches beyond individual components: the token layer’s structure, the naming convention, maturity levels’ exit criteria, breaking-change approval, and accessibility criteria. One of these being applied differently in two teams ends the system’s being a system.

Decisions that can be distributed are the ones that stay within a single component: adding an optional prop to a component, widening a value set, writing doc examples, designing product-specific components. The classification built in the previous lesson turns directly into an authorization rule here: additive contributions are distributed, breaking contributions stay centralized.

For this split to work, a third record is needed: ownership. Every component must have a named owner; a component with no owner is reviewed under no model. The ownership record is part of the catalog and is kept together with the maturity level defined in the first lesson.

Summary

  • Governance model is a choice between consistency and speed; the three arrangements — centralized, federated, hybrid — are defined by the variables capacity and review visibility. The centralized model’s capacity does not grow with the organization; the federated model’s capacity grows but its review visibility drops.
  • The centralized model’s cost is not the wait itself but the wait turning into local copies; the system stays good at what it reviews, but it stops reviewing most of the work.
  • Model choice depends on scale: the same three models favor the centralized model at four teams and the hybrid model at twelve. The tipping point is computed from the ratio of capacity to demand.
  • If the core’s approval capacity in the hybrid model does not keep up with the product teams’ preparation speed, the model turns into a centralized model called hybrid.
  • Unmet demand misleads when it is not reported; a low deviation number is deceptive unless shipped contributions and pending queue are reported together.
  • Decisions are distributed one by one: ones affecting multiple components stay centralized, ones staying within a single component are distributed; every component must have a written owner.

Next Step

In this lesson’s model, “local copy” was an assumption: it was assumed that a certain portion of the work waiting in the queue would leave the system. In a real organization, this number is not assumed, it is measured. The next lesson builds adoption measurement: it computes the ratio of system component usage to local copies through a repository scan, derives coverage percentage by team, produces a deviation list, and shows which local copy points to a component that should enter the catalog.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close