Lesson 03 / 10
Deployment Models
The measure of public, private, and hybrid deployment: in the same six-component workload, the public layout failing to place two components and six of seven call links failing to be established, control items kept running 8/24, 36/36, 20/36, and 28/36, fixed reserved capacity at 0%, 100%, 45%, and 75%, the elasticity window at 1.0, 21.0, 10.0, and 16.0 days, and hybrid paying 18 operating items, two identity directories, and six mapping items in both of its forms.
Published Updated
In this lesson
- Compares the same workload across three deployment layouts item by item and shows which component the data residency class forces where
- Reads four measures together: control items kept, fixed reserved capacity, the elasticity window, call links crossing the boundary
- Counts hybrid deployment's fixed cost that is independent of placement and works out what must be rebuilt at exit
Contents
The previous lesson measured the depth of renting: how the same decision set is split across three service models. Every number so far came out under one silent assumption — the rented service is drawn from a pool open to everyone. Yet the same service type can also be built in a layout reserved for a single organization, or part of the workload can run in one and the rest in the other.
These three options are named public cloud, private cloud, and hybrid cloud. In public cloud, resources come from a shared pool; in private cloud, the pool is reserved for a single organization; in hybrid cloud, the workload is split in two. This lesson sets up the same workload in all three and counts four items together: the item that stays under control, fixed reserved capacity, the elasticity window, and the constraint on where data can reside.
The Workload and the Residency Class
The example is the course’s fictional regional measurement network: the reading collector, the validator, billing, work-order, a nightly batch job, and the subscriber portal. Both the network and the components are fictional; the placement below is a model, and there is no real data center or contract. Where data can reside is treated here purely as a type; no regulation is named.
CC13: the workload is six components and seven call links; each component has a capacity share and a data residency class. CC14: there are three residency classes — unrestricted, within a bounded limit, on-premises only. CC15: the public layout satisfies the first two classes, the private layout satisfies all three; the hybrid layout satisfies them by splitting the components. CC16: there are six control items; on the public side two of them stay with the customer, on-premises all six do. CC17: the elasticity window is 1 fictional day on the public side and 21 on-premises; fixed reserved capacity is the capacity share of the components that fall on-premises. CC18: the operating-item set is nine and is run separately for each layout that is set up; if more than one layout is used, an identity mapping item is added for every component.
// cloud/deployment.mjs — the fictional measurement network's placement across three deployment // layouts (model): no real data center, real regulation, or real contract exists. No randomness. // residency class: unrestricted < bounded < on-premises (most restrictive) export const COMPONENT = ` collector 30 on-premises validator 20 bounded billing 15 on-premises work-order 10 bounded nightly-batch 15 unrestricted portal 10 bounded` .trim().split("\n").map((r) => { const [name, share, residency] = r.trim().split(/\s+/); return { name, share: +share, residency }; }); export const LINK = ` collector validator / validator billing / validator nightly-batch / billing work-order / portal billing / portal collector / work-order collector` .trim().split("/").map((r) => r.trim().split(/\s+/)); // Four user flows: each flow passes through call links one after another. export const FLOW = ` read-flow collector validator billing nightly-flow collector validator nightly-batch subscriber-query portal billing work-order field-flow work-order collector` .trim().split("\n").map((r) => { const [name, ...path] = r.trim().split(/\s+/); return { name, path }; }); // Six control items; only two stay with the customer on the public side, all six on-premises. export const CONTROL = ["physical-access", "hardware-lifespan", "neighboring-tenants", "patch-schedule", "log-access", "key-storage-location"]; export const PUBLIC_CONTROL = ["log-access", "key-storage-location"]; export const OPERATIONS = ["patch-pipeline", "monitoring", "backup", "identity", "network-rule", "capacity-plan", "log-collection", "release-rollout", "incident-procedure"]; export const WINDOW = { public: 1, private: 21 }; // elasticity window (fictional days) // Layout: each component lands on the "public" or "private" side; null = cannot be placed. export const LAYOUT = { public: (b) => (b.residency === "on-premises" ? null : "public"), private: () => "private", "narrow-hybrid": (b) => (b.residency === "on-premises" ? "private" : "public"), "wide-hybrid": (b) => (b.residency === "unrestricted" || b.name === "work-order" ? "public" : "private"), }; export function run(layoutName) { const place = Object.fromEntries(COMPONENT.map((b) => [b.name, LAYOUT[layoutName](b)])); const placed = COMPONENT.filter((b) => place[b.name]); const sides = [...new Set(placed.map((b) => place[b.name]))]; const totalShare = placed.reduce((a, b) => a + b.share, 0); const fixed = placed.filter((b) => place[b.name] === "private").reduce((a, b) => a + b.share, 0); const controlKept = placed.reduce((a, b) => a + (place[b.name] === "private" ? CONTROL.length : PUBLIC_CONTROL.length), 0); const window = placed.reduce((a, b) => a + b.share * WINDOW[place[b.name]], 0) / totalShare; const crossing = LINK.filter(([a, b]) => place[a] && place[b] && place[a] !== place[b]).length; const broken = LINK.filter(([a, b]) => !place[a] || !place[b]).length; const flow = FLOW.map((f) => { if (f.path.some((x) => !place[x])) return { name: f.name, crossings: null }; let n = 0; for (let i = 1; i < f.path.length; i++) if (place[f.path[i - 1]] !== place[f.path[i]]) n++; return { name: f.name, crossings: n }; }); return { layout: layoutName, flow, sides: sides.length, crossing, broken, directories: sides.length, unplaced: COMPONENT.length - placed.length, fixed: Math.round((fixed / totalShare) * 100), controlKept, cells: placed.length * CONTROL.length, window: window.toFixed(1), operations: OPERATIONS.length * sides.length, mapping: sides.length > 1 ? placed.length : 0 }; }
// cloud/measure.mjs — same workload in three deployment layouts: control, fixedness, elasticity, boundary cost. import { run, COMPONENT, LINK, FLOW, LAYOUT, CONTROL, OPERATIONS, WINDOW } from "./deployment.mjs"; const write = (w, ...s) => console.log(s.map((v, i) => (w[i] < 0 ? String(v).padEnd(-w[i]) : String(v).padStart(w[i]))).join("")); const L = Object.keys(LAYOUT), R = Object.fromEntries(L.map((l) => [l, run(l)])); console.log(`workload: ${COMPONENT.length} components, ${LINK.length} call links, ` + `${CONTROL.length} control items, ${OPERATIONS.length} operating items; ` + `elasticity window public ${WINDOW.public} / private ${WINDOW.private} days`); const A = [-16, 7, 12, 10, 15, 13]; console.log("\n1. which component lands where (by data residency class)"); write(A, "component", "share", ...L); for (const b of COMPONENT) write(A, b.name, b.share, ...L.map((l) => LAYOUT[l](b) ?? "unplaced")); const B = [-37, 10, 12, 15, 13]; console.log("\n2. same workload, item by item"); write(B, "measure", ...L); for (const [name, f] of [ ["unplaced components", (r) => r.unplaced], ["control items kept (components x 6)", (r) => `${r.controlKept}/${r.cells}`], ["fixed reserved capacity (%)", (r) => r.fixed], ["elasticity window (days, weighted)", (r) => r.window], ["number of layouts set up", (r) => r.sides]]) write(B, name, ...L.map((l) => f(R[l]))); const C = [-55, 10, 12, 15, 13]; console.log("\n3. hybrid's hidden cost"); write(C, "measure", ...L); for (const [name, f] of [ [`call links crossing the boundary (out of ${LINK.length})`, (r) => r.crossing], ["links that cannot be established (component unplaced)", (r) => r.broken], ["operating items run", (r) => r.operations], ["identity directories", (r) => r.directories], ["identity mapping items", (r) => r.mapping]]) write(C, name, ...L.map((l) => f(R[l]))); const F = [-36, 10, 12, 15, 13]; console.log("\n4. how many times each of the four user flows crosses the boundary (- = flow cannot be set up)"); write(F, "flow", ...L); FLOW.forEach((a, i) => write(F, `${a.name} (${a.path.length} stops)`, ...L.map((l) => R[l].flow[i].crossings ?? "-"))); write(F, "flows that can be set up", ...L.map((l) => R[l].flow.filter((a) => a.crossings !== null).length)); write(F, "total boundary crossings", ...L.map((l) => R[l].flow.reduce((a, x) => a + (x.crossings ?? 0), 0))); const E = [-38, 10, 12, 15, 13]; console.log("\n5. what is rebuilt at exit"); write(E, "measure", ...L); for (const [name, f] of [ ["layouts to tear down", (r) => r.sides], ["boundary links to rebuild", (r) => r.crossing], ["control items that do not carry over", (r) => r.cells - r.controlKept], ["control retained share (%)", (r) => Math.round((r.controlKept / r.cells) * 100)]]) write(E, name, ...L.map((l) => f(R[l])));
workload: 6 components, 7 call links, 6 control items, 9 operating items; elasticity window public 1 / private 21 days 1. which component lands where (by data residency class) component share public private narrow-hybrid wide-hybrid collector 30 unplaced private private private validator 20 public private public private billing 15 unplaced private private private work-order 10 public private public public nightly-batch 15 public private public public portal 10 public private public private 2. same workload, item by item measure public private narrow-hybrid wide-hybrid unplaced components 2 0 0 0 control items kept (components x 6) 8/24 36/36 20/36 28/36 fixed reserved capacity (%) 0 100 45 75 elasticity window (days, weighted) 1.0 21.0 10.0 16.0 number of layouts set up 1 1 2 2 3. hybrid's hidden cost measure public private narrow-hybrid wide-hybrid call links crossing the boundary (out of 7) 0 0 6 3 links that cannot be established (component unplaced) 6 0 0 0 operating items run 9 9 18 18 identity directories 1 1 2 2 identity mapping items 0 0 6 6 4. how many times each of the four user flows crosses the boundary (- = flow cannot be set up) flow public private narrow-hybrid wide-hybrid read-flow (3 stops) - 0 2 0 nightly-flow (3 stops) - 0 1 1 subscriber-query (3 stops) - 0 2 1 field-flow (2 stops) - 0 1 1 flows that can be set up 0 4 4 4 total boundary crossings 0 0 6 3 5. what is rebuilt at exit measure public private narrow-hybrid wide-hybrid layouts to tear down 1 1 2 2 boundary links to rebuild 0 0 6 3 control items that do not carry over 16 0 16 8 control retained share (%) 33 100 56 78
The numbers are in the measurement class; their inputs are CC13–CC18.
The Residency Constraint Is Not a Cost, It Is a Feasibility Gate
The first row of the second table is read before every other row: in the public layout, two
components cannot be placed at all. The collector holds raw meter readings, billing holds the
amount together with the subscriber identity; both fall into the on-premises class. Once these two
components cannot be placed, the links that cannot be established row in the third table erases
six of the seven links — leaving only the link between the validator and the nightly batch job.
This is not a trade-off question of the form “public cloud is cheaper but less controlled.” Before any trade-off is struck there is a feasibility gate: a single component’s residency class can eliminate an entire layout. The public layout’s 8/24 control items kept and its 1.0-day elasticity window are technically correct, but they apply to only four components; for the remaining two there is no number at all.
The private layout satisfies the constraint entirely and keeps 36 of the 36 control items. Its cost is in the bottom two rows: fixed reserved capacity is 100% and the elasticity window is 21.0 days. So the thirty-day wait the first lesson measured drops to twenty-one under the private layout, but not to zero; if the resource sits in the organization’s own facility, on-demand access is bounded by the organization’s own lead time.
Hybrid Is Not a Setting, It Is a Curve
The hybrid layout was set up in two forms. Narrow hybrid puts only the two required components on-premises: fixed capacity 45%, elasticity window 10.0 days, control items kept 20/36. But six of the seven call links cross the boundary — because the two components that fall on-premises sit at the center of the network, and almost every path runs through them.
Wide hybrid also moves the validator and the portal on-premises. Boundary-crossing links drop from six to three, and control items kept rise to 28/36. In exchange, fixed capacity climbs from 45% to 75%, and the elasticity window from 10.0 to 16.0 days.
Read side by side, the two hybrid columns show that the hybrid layout is not a switch but a curve: the only way to reduce boundary-crossing links is to move more components to the fixed side, and every component moved to the fixed side grows the elasticity window back. Gaining three boundary links back costs thirty points of fixed capacity and six days of elasticity window. In hybrid, the split line should sit not where the data class draws it, but at the thinnest point of the call graph — and these two places do not have to be the same.
Hybrid’s Fixed Entry Fee
The bottom three rows of the third table are identical across both hybrid columns: 18 operating items, 2 identity directories, 6 identity mapping items. The nine operating items are run separately for the two layouts; the patch pipeline is set up twice, monitoring twice, backup twice. Identity splits into two directories, and one mapping item is born for each of the six components.
This is an entry fee independent of placement. However well the split line is chosen, moving to a hybrid layout doubles operating items from nine to eighteen. The two single-layout options — public and private — write 9, 1, and 0 on these rows. Hybrid offers a middle path between control and elasticity, but there is a fixed fee at the gate of that middle path, and the fee grows as the component count grows.
Where the Boundary Runs
The fourth table converts the link count into user flows. Under the public layout, all four flows fail to be set up — every flow’s path has an unplaceable component sitting on it. The total-boundary-crossings column reads zero there, but that zero is not a success, it is the result of there being no flow at all; if the two rows are not read together, the table misleads.
Under narrow hybrid, the read flow crosses the boundary twice, the subscriber query twice, and the nightly flow and the field flow once each. Under wide hybrid, the read flow never touches the boundary at all; each of the remaining three flows crosses once. When the split line pulls the validator onto the on-premises side, the most frequently run flow collects entirely on one side; the price paid is that the validator’s 20-unit capacity share is no longer elastic.
What Is Rebuilt at Exit
The fifth table counts the exit. Under the single-layout options, one layout must be torn down and there are no boundary links to rebuild. Under hybrid, two layouts are torn down and the boundary links — six or three — must be rebuilt from scratch in the new place. Control items that do not carry over are 16 under public, 16 under narrow hybrid, 8 under wide hybrid, and 0 under private.
The last row turns the course’s measurement axis onto this lesson: the control-retained share is 33%, 100%, 56%, and 78%. The lower this share, the more items must be renegotiated at exit. Narrow hybrid holds 56% control and carries six boundary links; wide hybrid holds 78% and carries three links — but both have paid the same fixed entry fee.
Summary
- The public layout cannot place two of the six components, and six of the seven call links cannot be established; the residency class is not a trade-off item but a feasibility gate that comes before any trade-off.
- Control items kept are 8/24, 36/36, 20/36, and 28/36; in exchange, fixed reserved capacity is 0%, 100%, 45%, and 75%, and the elasticity window is 1.0, 21.0, 10.0, and 16.0 days.
- The private layout keeps every control item, but the elasticity window stays at 21.0 days: if the resource sits in the organization’s own facility, on-demand access is bounded by the organization’s own lead time.
- Hybrid is not a switch but a curve: dropping boundary-crossing links from 6 to 3 raises fixed capacity from 45% to 75% and the elasticity window from 10.0 to 16.0 days. Across the four user flows, total boundary crossings drop from 6 to 3, and under wide hybrid the read flow never touches the boundary at all.
- Hybrid’s hidden cost is independent of placement and identical in both of its forms: 18 operating items (the nine run twice), 2 identity directories, 6 identity mapping items.
- At exit, hybrid tears down two layouts and rebuilds either six or three boundary links; the control-retained share is 33%, 100%, 56%, and 78%.
Next Step
This lesson compared deployment layouts in terms of control, fixedness, and elasticity; no money changed hands in any of it. Yet the difference between “100% fixed reserved capacity” and “0%” really shows itself in a payment form: one up front and once, the other continuous and by usage. The next lesson runs the same workload between capital expense and operating expense, works out the break-even point, and counts where that point shifts as the usage curve changes. Prices are fictional and are written in a fictional unit.
To keep your progress and take notes, Log in
My notes
Log in to take notes.