Skip to content
VLSI Mentor

CXL · Module 23

Composable Infrastructure

A fixed SKU has a ratio, and a workload that does not match it over-buys. This chapter builds SKU rigidity, compose fit, bind latency, fragmentation, instance lifetime, generation mixing, series reliability, control-plane scale, composable TCO and the assembled model.

23.1 found a quarter of a fleet's DRAM bought and unreachable, and pooled it. This chapter asks the obvious next question: if memory can be attached to any socket at boot, what else can — and what is a server once its parts are chosen at allocation time rather than at purchase time?

The answer is genuinely better on the axis it was built for. A fixed SKU has a ratio, and a workload that does not match it over-buys whichever resource it does not need — 75% of the cores, in the case section 5 opens with. Composing from a pool removes that strand exactly.

It also introduces five costs the fixed SKU did not have, and four of them are ways a machine can fail that a bought machine could not. That asymmetry is what this chapter is for.

1. The Engineering Problem — A SKU Has A Ratio

A fixed SKU strands whichever resource it over-buys. An 8-core, 128 GB SKU serving a workload wanting 8 cores and 512 GB buys 32 cores and strands 24 — 75%. Section 5.

Composing means every resource type must be there, not the one you checked. A machine short only on accelerators is a machine that does not compose. Section 6.

A composed machine boots slower. Sixteen binds at 250 ms each on an 8-second boot is a 50% start-up overhead. Section 7.

And free capacity is not composable capacity. 512 GB free across four domains, none holding more than 128, refuses a 256 GB request. Section 8.

A machine built from four borrowed parts fails four times as often. Four year-long parts make a quarter-year machine. Section 12.

This chapter against 23.1, stated precisely. That one owns pooling one resource type. This one owns assembling a machine from several pools — which is why sections 6, 12 and 13 have no counterpart there: they are all consequences of a machine having more than one borrowed part.

2. The One-Sentence Model

Composing beats buying when machines really are assembled, the SKU strand is genuinely gone, every resource type is checked before the compose is promised, bind time is inside the start-up budget, no machine spans generations, and the fabric manager can track the compose rate — and every defect below is a fleet that assembles machines and is worse off for it.

3. What This Chapter Owns

GroundOwner
Pooling one resource type, and its costs23.1
Utilisation measurement and reporting23.3
Hyperscaler deployment patterns23.4
Fabric topology and switch depth21.3
Multi-tenant isolation and QoS19.2
Assembling a machine from several poolsthis chapter

Deferred:

Deferred groundOwner
Memory blast radius and reclaim23.1 §7 · §10
Fabric-attached device discovery21.1
Accelerator coherence and attach22.1
Cryptographic primitivesout of scope — see §4

4. Teaching-Model Boundary

Every model is a small synchronous block isolating one property. A real composable system is a fabric manager, a switch, several device classes, a BMC, a scheduler and an inventory database, and none of that is reproduced. What is reproduced is the arithmetic each has to get right, and the shape of the mistake when it does not.

Each model is built twice — a correct build and a broken build selected by a parameter. Every broken build here is the fixed-SKU mental model applied to a composed machine. The ratio matches. The machine boots. The parts are one generation. The chassis is what fails. Each was true when the server arrived on a pallet, and each stops being true the moment its parts are chosen independently.

A block diagram of SKU rigidity. A workload needing eight cores and 512 gigabytes is provisioned on an eight-core, 128 gigabyte SKU. The memory requirement binds, forcing four servers, which provides 32 cores against a need for eight — 24 cores stranded. A composed machine takes eight cores and 512 gigabytes from separate pools with nothing stranded.the workload8 cores · 512 GBa fixed SKU8 cores · 128 GBcomposedfrom two pools4 servers32 cores bought24 stranded75% of the coresexact fitnothing strandedbought asassembled asmemory bindsthe costthe gain12

Figure 1 — The top path is the whole case for composability, and it is a good one. The bottom path costs nothing on this diagram, which is exactly why sections 6 through 13 exist: the gain is one number and the price is five.

5. RTL 1 — A Fixed SKU Strands Whatever It Over-Buys

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 1 - a fixed SKU has a ratio. A workload whose ratio differs is provisioned
// by whichever resource binds, and the other is bought and unused.
module sku_rigidity #(parameter int ASSUME_RATIO_MATCHES = 0) (
  input  logic clk, rst_n,
  input  logic        size_it,
  input  logic [15:0] sku_cpu, sku_mem_gb, need_cpu, need_mem_gb,
  output logic [15:0] servers, provisioned_cpu, stranded_cpu, stranded_pct,
  output logic        balanced,
  output logic [7:0]  n_sizings, n_rigid,
  output logic        strand_hidden_err
);
  logic [31:0] c_q, m_q, p_q, s_q;
  logic [15:0] by_cpu, by_mem;
  assign c_q = (sku_cpu == 16'd0) ? 32'd0
             : (({16'd0, need_cpu} + {16'd0, sku_cpu} - 32'd1) / {16'd0, sku_cpu});
  assign by_cpu = (c_q > 32'd65535) ? 16'hFFFF : c_q[15:0];
  assign m_q = (sku_mem_gb == 16'd0) ? 32'd0
             : (({16'd0, need_mem_gb} + {16'd0, sku_mem_gb} - 32'd1)
                / {16'd0, sku_mem_gb});
  assign by_mem = (m_q > 32'd65535) ? 16'hFFFF : m_q[15:0];
  // The SKU count is set by whichever resource needs more servers.
  assign servers = (by_cpu > by_mem) ? by_cpu : by_mem;
  assign p_q = {16'd0, servers} * {16'd0, sku_cpu};
  assign provisioned_cpu = (p_q > 32'd65535) ? 16'hFFFF : p_q[15:0];
  // A model that assumes the workload matches the SKU ratio sees no strand.
  assign stranded_cpu = (ASSUME_RATIO_MATCHES != 0) ? 16'd0
                      : ((provisioned_cpu > need_cpu)
                         ? (provisioned_cpu - need_cpu) : 16'd0);
  assign s_q = (provisioned_cpu == 16'd0) ? 32'd0
             : (({16'd0, stranded_cpu} * 32'd100) / {16'd0, provisioned_cpu});
  assign stranded_pct = (s_q > 32'd65535) ? 16'hFFFF : s_q[15:0];
  assign balanced = (stranded_pct <= 16'd25);
  // Cores bought and unused, reported as matched to the workload.
  assign strand_hidden_err = size_it && (provisioned_cpu > need_cpu)
                             && (stranded_cpu == 16'd0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_sizings <= 8'd0; n_rigid <= 8'd0;
    end else if (size_it) begin
      n_sizings <= n_sizings + 8'd1;
      if (!balanced) n_rigid <= n_rigid + 8'd1;
    end
  end
endmodule

Eight sizings. An 8-core, 128 GB SKU.

Cores / memory wantedServers · Cores bought · Stranded · Share
8 / 512 GB4 · 32 · 24 cores · 75% — the memory binds
32 / 512 GB4 · 32 · 0 · 0% — the ratio matches exactly
8 / 1024 GB8 · 64 · 56 cores · 87%
32 / 128 GB4 · 32 · 0 · the memory is stranded instead
24 / 512 GB4 · 32 · 8 cores · exactly 25% · exactly balanced
nothing wanted0 · 0 · 0 · nothing to strand
9 / 128 GB2 · 16 · 7 cores · 43% — nine cores need two SKUs
8 / 500 GB4 · 32 · 24 cores · 75% — 500 GB needs four

Four sizings were rigid; the ratio-matched model reported none.

This is 23.1 §5's strand with a second dimension, and the second dimension is what makes it unfixable by packing. There, a socket's memory stranded because no other socket could reach it. Here the cores strand because the memory forced a server count, and no amount of bin-packing helps: the ratio is soldered.

Row four is the honest limit of a one-sided model. A core-heavy workload strands no cores — it strands memory, symmetrically, and this model does not measure that. The finding is not "cores strand"; it is "whichever resource does not bind, strands", and section 27 exercise 1 is the symmetric version.

Rows seven and eight are the rounding, and they matter more than they look. Nine cores need two SKUs, not one and a bit. Five hundred gigabytes needs four, not three and a bit. A SKU count is a ceiling, and the remainder is bought in full — which section 17 records as the source of this chapter's only two mutation survivors.

6. RTL 2 — Every Resource Type Must Be There

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 2 - composing needs every resource type. A compose succeeds only if the
// pool has enough of all of them, not enough of the one that was checked.
module compose_fit #(parameter int IGNORE_INVENTORY = 0) (
  input  logic clk, rst_n,
  input  logic        compose,
  input  logic [15:0] pool_cpu, pool_mem_gb, pool_accel,
  input  logic [15:0] need_cpu, need_mem_gb, need_accel,
  output logic [1:0]  short_types,
  output logic [15:0] worst_short,
  output logic        cpu_ok, mem_ok, accel_ok, composable,
  output logic [7:0]  n_composes, n_failed,
  output logic        partial_check_err
);
  logic [15:0] cpu_gap, mem_gap, accel_gap, biggest;
  assign cpu_ok   = (need_cpu    <= pool_cpu);
  assign mem_ok   = (need_mem_gb <= pool_mem_gb);
  assign accel_ok = (need_accel  <= pool_accel);
  assign cpu_gap   = cpu_ok   ? 16'd0 : (need_cpu    - pool_cpu);
  assign mem_gap   = mem_ok   ? 16'd0 : (need_mem_gb - pool_mem_gb);
  assign accel_gap = accel_ok ? 16'd0 : (need_accel  - pool_accel);
  assign biggest = (cpu_gap > mem_gap) ? cpu_gap : mem_gap;
  assign worst_short = (biggest > accel_gap) ? biggest : accel_gap;
  assign short_types = {1'b0, ~cpu_ok} + {1'b0, ~mem_ok} + {1'b0, ~accel_ok};
  // Checking one resource type is what a CPU-shaped scheduler does.
  assign composable = (IGNORE_INVENTORY != 0) ? cpu_ok
                                              : (cpu_ok && mem_ok && accel_ok);
  // A compose declared possible while some resource type was short.
  assign partial_check_err = compose && composable && (short_types != 2'd0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_composes <= 8'd0; n_failed <= 8'd0;
    end else if (compose) begin
      n_composes <= n_composes + 8'd1;
      if (!composable) n_failed <= n_failed + 8'd1;
    end
  end
endmodule

Six composes. A pool of 64 cores, 1024 GB and eight accelerators.

Cores / memory / accelerators wantedTypes short · Worst gap · Composable
16 / 512 GB / 40 · 0 · yes
16 / 512 GB / 161 — the accelerators · 8 · no, and a CPU-only check says yes
128 / 512 GB / 41 — the cores · 64 · no, and the CPU-only check agrees
64 / 1024 GB / 80 · 0 · yes, exactly emptying the pool
nothing wanted0 · 0 · yes, trivially
128 / 2048 GB / 163 — all of them · 1024 · no

Three composes failed when every type is checked; two when only the cores are.

A compose is a conjunction and a scheduler is usually a CPU scheduler. Row two is the failure that matters: cores and memory are plentiful, the accelerators are not, and a scheduler that grew up placing pods by CPU request finds nothing wrong. The machine is promised, the bind fails, and the error surfaces somewhere with no context.

Row three is why the broken build survives review. When the cores really are the binding resource, the CPU-only check is right — and on a fleet whose workloads are mostly CPU-bound it is right most of the time. A check that is correct on the common case and silent on the rare one is the hardest kind to find.

Row six is worth reporting rather than reducing. All three types short is not "more broken"; it is a different operational answer — the fleet is out of everything, which is a capacity problem rather than a placement one, and short_types exists so the two can be told apart.

7. RTL 3 — A Composed Machine Boots Slower

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 3 - composing takes time. Every resource has to be bound and enumerated
// before the machine boots, and that is added to every instance start.
module compose_latency #(parameter int INSTANT_COMPOSE = 0) (
  input  logic clk, rst_n,
  input  logic        compose_it,
  input  logic [15:0] resources, bind_ms, boot_ms,
  output logic [15:0] compose_ms, added_ms, overhead_pct,
  output logic        acceptable,
  output logic [7:0]  n_composes, n_slow,
  output logic        bind_ignored_err
);
  logic [31:0] c_q, o_q;
  assign c_q = (INSTANT_COMPOSE != 0) ? {16'd0, boot_ms}
             : ({16'd0, boot_ms} + ({16'd0, resources} * {16'd0, bind_ms}));
  assign compose_ms = (c_q > 32'd65535) ? 16'hFFFF : c_q[15:0];
  // compose_ms is boot_ms plus a non-negative term, so this cannot underflow.
  assign added_ms = compose_ms - boot_ms;
  assign o_q = (boot_ms == 16'd0) ? 32'd0
             : (({16'd0, added_ms} * 32'd100) / {16'd0, boot_ms});
  assign overhead_pct = (o_q > 32'd65535) ? 16'hFFFF : o_q[15:0];
  assign acceptable = (overhead_pct <= 16'd25);
  // A composed instance costed as if its resources were already attached.
  assign bind_ignored_err = compose_it && (resources != 16'd0) && (bind_ms != 16'd0)
                            && (compose_ms == boot_ms);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_composes <= 8'd0; n_slow <= 8'd0;
    end else if (compose_it) begin
      n_composes <= n_composes + 8'd1;
      if (!acceptable) n_slow <= n_slow + 8'd1;
    end
  end
endmodule

Six composes. An 8-second boot, 250 ms to bind each resource.

Resources boundTotal start · Added · Overhead · Acceptable
49.0 s · 1.0 s · 12% · yes
1612.0 s · 4.0 s · 50% · no
0 — nothing to bind8.0 s · 0 · 0% · yes
810.0 s · 2.0 s · exactly 25% · exactly acceptable
4, boot unmeasured1.0 s · 1.0 s · no baseline · —
4, binds are instant8.0 s · 0 · 0% · yes

One compose was too slow; the instant-compose model reported none.

Bind time is linear in the number of parts, which is the thing composability increases. A machine with four borrowed resources costs 12%; a machine with sixteen costs half its boot again, and the whole point of composability is that the parts count is a free variable.

Row four is the design rule this gives you. At 250 ms per bind on an 8-second boot, eight resources is the threshold — and that is a number a fabric manager's designers can act on, either by reducing per-bind cost or by binding in parallel.

Row five is the model declining to divide by an unmeasured baseline, exactly as 23.1 §8 does. A percentage against a denominator nobody measured is not a small error; it is a number with no meaning at all, and reporting the added milliseconds is the honest alternative.

An eight-cycle waveform of composing a machine. Four resources are bound in sequence over the first four cycles, then the machine boots for three cycles and becomes ready. A second trace shows a pre-built server that boots immediately, becoming ready three cycles earlier.compose requestedcompose requestedlast bind donelast bind donepre-built readypre-built readycomposed readycomposed readyclkbind_cpubind_membind_accelbind_nicbootingprebuiltreadyt0t1t2t3t4t5t6t7
Figure 2 — The four bind rows are section 7's added time, paid once per instance and once per resource. The prebuilt row is the same machine bought rather than assembled: it starts booting at cycle 0 and is ready at cycle 5, three cycles before the composed one. Nothing is wrong in either trace — the composed machine simply has more to do first.

The bind rows are the whole difference and they are strictly additive. No amount of faster boot recovers them, and the only levers are fewer resources or parallel binding — which is a fabric-manager design decision rather than an operational one.

8. RTL 4 — Free Capacity Is Not Composable Capacity

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 4 - fragmentation. A compose draws from one fabric domain, so free
// capacity spread across domains is not capacity a single machine can have.
module fragmentation #(parameter int IGNORE_FRAGMENTATION = 0) (
  input  logic clk, rst_n,
  input  logic        allocate,
  input  logic [15:0] free_gb, largest_domain_gb, request_gb,
  output logic [15:0] fragmented_gb, usable_gb,
  output logic        satisfiable,
  output logic [7:0]  n_allocations, n_denied,
  output logic        fragmentation_ignored_err
);
  // Capacity that is free but not reachable from any single domain.
  assign fragmented_gb = (free_gb > largest_domain_gb)
                         ? (free_gb - largest_domain_gb) : 16'd0;
  // A model that ignores fragmentation offers the sum of every domain.
  assign usable_gb = (IGNORE_FRAGMENTATION != 0) ? free_gb : largest_domain_gb;
  assign satisfiable = (request_gb <= usable_gb);
  // A request granted against capacity no single domain can supply.
  assign fragmentation_ignored_err = allocate && satisfiable
                                     && (request_gb > largest_domain_gb);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_allocations <= 8'd0; n_denied <= 8'd0;
    end else if (allocate) begin
      n_allocations <= n_allocations + 8'd1;
      if (!satisfiable) n_denied <= n_denied + 8'd1;
    end
  end
endmodule

Six allocations. 512 GB free in the fleet.

Largest domain / requestFragmented · Usable by one machine · Satisfiable
128 GB / 256 GB384 GB · 128 · no — despite 512 free
128 GB / 128 GB384 · 128 · yes, exactly
128 GB / 64 GB384 · 128 · yes
512 GB / 256 GB0 · 512 · yes — one domain holds it all
nothing free / 64 GB0 · 0 · no
128 GB / 512 GB384 · 128 · no, and the whole-pool model thinks it exactly fits

Three allocations were denied when domains are respected; one when they are not.

A dashboard's free-capacity figure is a sum and a compose needs a maximum. Those are the same number only when the pool is one domain, and they diverge exactly as the fleet grows — which is the direction every composable deployment goes.

Row six is the sharpest form of the failure. A 512 GB request against 512 GB free reads as an exact fit, and there is no single domain that can supply a byte over 128. The whole-pool model does not merely over-count; it produces a machine specification that cannot be built anywhere in the fleet.

This is 23.1 §12's contention with a different cause and the same symptom. There, the pool was short because other sockets held the memory. Here it is not short at all — the capacity is free, idle, and in the wrong place, which is a scheduling problem rather than a capacity one and needs a completely different fix.

9. RTL 5 — Bind Time Is Paid In Full By Short Instances

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 5 - composing and decomposing cost time that a short-lived instance pays
// in full, because the overhead does not shrink with the lifetime.
module bind_lifetime #(parameter int ASSUME_STATIC = 0) (
  input  logic clk, rst_n,
  input  logic        run,
  input  logic [15:0] lifetime_min, compose_s, decompose_s,
  output logic [15:0] overhead_s, lifetime_s, overhead_pct,
  output logic        acceptable,
  output logic [7:0]  n_runs, n_churn,
  output logic        bind_free_err
);
  logic [31:0] l_q, o_q;
  // A statically composed machine pays this once and never again; a machine
  // composed per workload pays it every time.
  assign overhead_s = (ASSUME_STATIC != 0) ? 16'd0 : (compose_s + decompose_s);
  assign l_q = {16'd0, lifetime_min} * 32'd60;
  assign lifetime_s = (l_q > 32'd65535) ? 16'hFFFF : l_q[15:0];
  assign o_q = (lifetime_s == 16'd0) ? 32'd65535
             : (({16'd0, overhead_s} * 32'd100) / {16'd0, lifetime_s});
  assign overhead_pct = (o_q > 32'd65535) ? 16'hFFFF : o_q[15:0];
  assign acceptable = (overhead_pct <= 16'd10);
  // Composing and tearing down reported as costing nothing.
  assign bind_free_err = run && (compose_s != 16'd0) && (overhead_s == 16'd0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_runs <= 8'd0; n_churn <= 8'd0;
    end else if (run) begin
      n_runs <= n_runs + 8'd1;
      if (!acceptable) n_churn <= n_churn + 8'd1;
    end
  end
endmodule

Six runs. Twelve seconds to compose, six to tear down — eighteen either way.

Instance lifetimeOverhead · Life in seconds · Share · Acceptable
5 minutes18 s · 300 · 6% · yes
1 minute18 s · 60 · 30% · no
1 hour18 s · 3600 · under 1% · yes
unstated18 s · 0 · unbounded · no
3 minutes18 s · 180 · exactly 10% · exactly acceptable
5 minutes, instant bind0 · 300 · 0% · yes

Two runs were churning; the static model reported one.

The overhead is fixed and the lifetime is not, so composability has a minimum useful instance duration. At eighteen seconds of bind and teardown, three minutes is the floor — and a fleet of one-minute jobs spends 30% of its machine-time assembling and dismantling machines.

That is the single most important scoping question for a composable deployment, and it is answered by the workload rather than the hardware. Long-lived database and training instances amortise the bind to nothing. Short-lived batch and serverless workloads are the ones composability is usually pitched at, and they are the ones it suits worst.

Row six is where the static model is right, and it is not a strawman: a machine composed once at rack commissioning and left alone genuinely pays nothing per workload. The error is applying that model to a machine composed per job, which is precisely the deployment being sold.

10. RTL 6 — A Pool Holds Generations

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 6 - a pool holds generations. A machine composed across them runs at the
// slowest part it was given, not at the fastest part available.
module heterogeneity #(parameter int ASSUME_UNIFORM = 0) (
  input  logic clk, rst_n,
  input  logic        compose,
  input  logic        mixed,
  input  logic [15:0] gen_a_gbps, gen_b_gbps,
  output logic [15:0] fastest_gbps, effective_gbps, loss_gbps, loss_pct,
  output logic        acceptable,
  output logic [7:0]  n_composes, n_degraded,
  output logic        uniform_assumed_err
);
  logic [15:0] slowest;
  logic [31:0] p_q;
  assign fastest_gbps = (gen_a_gbps > gen_b_gbps) ? gen_a_gbps : gen_b_gbps;
  assign slowest      = (gen_a_gbps > gen_b_gbps) ? gen_b_gbps : gen_a_gbps;
  // A mixed machine runs at its slowest part. A model that assumes one
  // generation reports the fastest part in the pool.
  assign effective_gbps = (ASSUME_UNIFORM != 0) ? fastest_gbps
                        : (mixed ? slowest : fastest_gbps);
  // effective_gbps is either the fastest or the slowest, so this cannot underflow.
  assign loss_gbps = fastest_gbps - effective_gbps;
  assign p_q = (fastest_gbps == 16'd0) ? 32'd0
             : (({16'd0, loss_gbps} * 32'd100) / {16'd0, fastest_gbps});
  assign loss_pct = (p_q > 32'd65535) ? 16'hFFFF : p_q[15:0];
  assign acceptable = (loss_pct <= 16'd20);
  // A machine spanning generations reported at the newer one's rate.
  assign uniform_assumed_err = compose && mixed && (gen_a_gbps != gen_b_gbps)
                               && (loss_gbps == 16'd0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_composes <= 8'd0; n_degraded <= 8'd0;
    end else if (compose) begin
      n_composes <= n_composes + 8'd1;
      if (!acceptable) n_degraded <= n_degraded + 8'd1;
    end
  end
endmodule

Six composes.

Parts / mixedFastest available · Effective · Lost · Share
800 and 400 Gbps / yes800 · 400 · 400 · 50%
800 and 400 / no800 · 800 · 0 · 0%
800 and 800 / yes800 · 800 · 0 · 0% — spanning costs nothing
400 and 800 / yes800 · 400 · 400 · 50% — the same, either way round
800 and 640 / yes800 · 640 · 160 · exactly 20% · exactly acceptable
unmeasured / yes0 · 0 · 0 · no rate to report

Two composes were degraded; the uniform model reported none.

A pool accumulates generations because it is refreshed incrementally, which is the operational model composability makes possible and attractive. The consequence is that a machine drawn from it can span three years of silicon, and it runs at whatever the oldest part can do.

Rows one and four are the same case with the operands swapped, and both are driven deliberately. 21.4 established that symmetric operands hide gaps — testing "the first part is slower" is not testing "the second part is slower" — and the fix is to drive both rather than to reason that they are equivalent.

Row three is the case that makes the check honest. Two parts of the same speed can be spanned freely; the error is not mixing, it is mixing across a performance gap, which is why uniform_assumed_err requires the rates to actually differ.

11. RTL 7 — A Machine's Reliability Divides By Its Parts

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 7 - a composed machine fails when any borrowed part fails, so its mean
// time between failures is the part's divided by the number of parts.
module failure_attribution #(parameter int BLAME_THE_SERVER = 0) (
  input  logic clk, rst_n,
  input  logic        assess,
  input  logic [15:0] parts, part_mtbf_h,
  output logic [15:0] composite_mtbf_h, lost_h_per_year,
  output logic        acceptable,
  output logic [7:0]  n_assessments, n_fragile,
  output logic        parts_ignored_err
);
  logic [31:0] c_q, l_q;
  // A model that blames the chassis reports the chassis's own reliability.
  assign c_q = (BLAME_THE_SERVER != 0) ? {16'd0, part_mtbf_h}
             : ((parts == 16'd0) ? {16'd0, part_mtbf_h}
                : ({16'd0, part_mtbf_h} / {16'd0, parts}));
  assign composite_mtbf_h = (c_q > 32'd65535) ? 16'hFFFF : c_q[15:0];
  assign l_q = (composite_mtbf_h == 16'd0) ? 32'd65535
             : (32'd8760 / {16'd0, composite_mtbf_h});
  assign lost_h_per_year = (l_q > 32'd65535) ? 16'hFFFF : l_q[15:0];
  assign acceptable = (composite_mtbf_h >= 16'd4380);
  // A composed machine's reliability quoted as one part's.
  assign parts_ignored_err = assess && (parts > 16'd1)
                             && (composite_mtbf_h == part_mtbf_h);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_assessments <= 8'd0; n_fragile <= 8'd0;
    end else if (assess) begin
      n_assessments <= n_assessments + 8'd1;
      if (!acceptable) n_fragile <= n_fragile + 8'd1;
    end
  end
endmodule

Six assessments. Parts that each last a year — 8760 hours.

Borrowed partsMachine MTBF · Failures a year · Acceptable
42190 h — a quarter year · 4 · no
18760 h · 1 · yes — it is just a server
81095 h — six weeks · 8 · no
24380 h · 2 · exactly acceptable
none declared8760 h · 1 · nothing to divide by
17520rounds to nothing · unbounded · not a machine that runs

Three assessments were fragile; the chassis model reported none.

This is 22.5 §9's arithmetic at the scale of one machine, and it is the same surprise. Reliability divides. A machine assembled from four excellent parts is four times worse than any of them, and nothing about any part changed.

The chassis model is not laziness; it is the only model a bought server ever needed. A server's reliability was a single vendor number for a single sealed unit. Composability turns it into a series calculation over parts from different vendors on different maintenance schedules, and that is a category change in how a fleet is reasoned about, not a worse number.

Row four gives the practical bound. At a half-year acceptance threshold, two borrowed parts is the limit for parts with a one-year life — which means either fewer parts, better parts, or an acceptance threshold that admits the truth.

A block diagram of a composed machine's series reliability. Four borrowed parts — cores, memory, an accelerator and a network interface — each last a year on their own. The machine fails when any one of them fails, giving a composite mean time between failures of 2190 hours, a quarter of a year, and four failures annually.cores8760 hmemory8760 haccelerator8760 hthe machineany part fails2190 hoursa quarter year4 a yearnot 1in seriesin seriesin seriescompositeoutages12

Figure 3 — Three excellent parts and a fourth off-diagram, each a year between failures, assembled into a machine that fails every eleven weeks. The parts are in series and nothing in the picture is defective — which is why a per-part reliability review passes and the machine still does not stay up.

12. RTL 8 — The Control Plane Is A Resource Too

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 8 - the control plane is a resource too. Every compose is work for the
// fabric manager, and a fleet cannot compose faster than it can be tracked.
module orchestration_scale #(parameter int IGNORE_CONTROL_PLANE = 0) (
  input  logic clk, rst_n,
  input  logic        schedule,
  input  logic [15:0] demand_per_min, capacity_per_min,
  output logic [15:0] served_per_min, backlog_per_min, backlog_pct,
  output logic        keeps_up,
  output logic [7:0]  n_schedules, n_backlogged,
  output logic        control_plane_ignored_err
);
  logic [31:0] p_q;
  // A model that ignores the control plane serves whatever is asked for.
  assign served_per_min = (IGNORE_CONTROL_PLANE != 0) ? demand_per_min
                        : ((demand_per_min > capacity_per_min) ? capacity_per_min
                                                               : demand_per_min);
  // served_per_min is a minimum against demand_per_min, so this cannot underflow.
  assign backlog_per_min = demand_per_min - served_per_min;
  assign p_q = (demand_per_min == 16'd0) ? 32'd0
             : (({16'd0, backlog_per_min} * 32'd100) / {16'd0, demand_per_min});
  assign backlog_pct = (p_q > 32'd65535) ? 16'hFFFF : p_q[15:0];
  assign keeps_up = (backlog_per_min == 16'd0);
  // A compose rate promised beyond what the fabric manager can track.
  assign control_plane_ignored_err = schedule && (demand_per_min > capacity_per_min)
                                     && (served_per_min == demand_per_min);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_schedules <= 8'd0; n_backlogged <= 8'd0;
    end else if (schedule) begin
      n_schedules <= n_schedules + 8'd1;
      if (!keeps_up) n_backlogged <= n_backlogged + 8'd1;
    end
  end
endmodule

Five schedules. A fabric manager that can track sixty composes a minute.

Composes demandedServed · Queued · Share queued · Keeps up
120 a minute60 · 60 · 50% · no
60 a minute60 · 0 · 0% · yes, exactly
30 a minute30 · 0 · 0% · yes
120, control plane down0 · 120 · 100% · no
none demanded0 · 0 · 0% · trivially

Two schedules were backlogged; the model that ignores the control plane reported none.

Composability replaces a purchasing decision with a per-instance operation, and per-instance operations have a rate limit. A fixed-SKU fleet composes zero machines a minute forever; a composable fleet composes one per instance start, and the fabric manager is the only thing tracking every binding.

Row two is the sizing rule and it is the whole model. The control plane's capacity is a specification, the instance start rate is a workload property, and section 9's short-lived instances are exactly the ones that generate the highest compose rate — the two failure modes reinforce each other.

Row four is the failure nobody plans for. A control plane that is down does not degrade the fleet's existing machines at all; it makes the fleet unable to create new ones, which looks like a total outage to anything that autoscales and like nothing at all to anything already running.

13. RTL 9 — What Composability Costs

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 9 - what composability costs. A better fit against an orchestration layer
// that fixed-SKU racks do not need at all.
module composable_tco #(parameter int IGNORE_ORCHESTRATION = 0) (
  input  logic clk, rst_n,
  input  logic        price,
  input  logic [15:0] fixed_cost, composed_resource_cost, orchestration_cost,
  input  logic [15:0] workloads,
  output logic [15:0] composed_total, fixed_per_workload, composed_per_workload,
  output logic        composing_cheaper,
  output logic [7:0]  n_pricings, n_wins,
  output logic        orchestration_ignored_err
);
  logic [31:0] t_q, f_q, c_q;
  // The orchestration layer is a cost fixed SKUs do not carry.
  assign t_q = {16'd0, composed_resource_cost}
             + ((IGNORE_ORCHESTRATION != 0) ? 32'd0 : {16'd0, orchestration_cost});
  assign composed_total = (t_q > 32'd65535) ? 16'hFFFF : t_q[15:0];
  assign f_q = (workloads == 16'd0) ? 32'd65535
             : (({16'd0, fixed_cost} * 32'd100) / {16'd0, workloads});
  assign fixed_per_workload = (f_q > 32'd65535) ? 16'hFFFF : f_q[15:0];
  assign c_q = (workloads == 16'd0) ? 32'd65535
             : (({16'd0, composed_total} * 32'd100) / {16'd0, workloads});
  assign composed_per_workload = (c_q > 32'd65535) ? 16'hFFFF : c_q[15:0];
  assign composing_cheaper = (composed_per_workload < fixed_per_workload);
  // A composed cost that does not carry the orchestration it needs.
  assign orchestration_ignored_err = price && (orchestration_cost != 16'd0)
                                     && (composed_total == composed_resource_cost);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_pricings <= 8'd0; n_wins <= 8'd0;
    end else if (price) begin
      n_pricings <= n_pricings + 8'd1;
      if (composing_cheaper) n_wins <= n_wins + 8'd1;
    end
  end
endmodule

Five pricings. Fixed racks at 4000 against composed resources at 2848, over forty workloads.

Orchestration costComposed total · Per hundred workloads · Cheaper than the fixed 10,000
8003648 · 9120 · yes
02848 · 7120 · yes
20004848 · 12,120 · no
800, no workloads3648 · unbounded · neither is cheaper
11524000 · exactly 10,000 · exactly equal — not cheaper

Two wins when the orchestration is costed; four when it is not.

The resource saving is real and the orchestration layer is real, and they are on different budgets. Composed resources cost 2848 against 4000 of fixed racks — a 29% saving that any procurement exercise will find. The fabric manager, its high-availability deployment, its integration and the team that runs it are on nobody's hardware line.

Row five is the break-even and it is the figure to compute first. At an orchestration cost of 1152 the two are exactly equal, which means any orchestration layer costing less than 29% of the fixed-rack spend wins and any layer costing more loses. That is one ratio, available before anything is bought, and it decides the programme.

This is 23.1 §13's structure with a different denominator, and the pairing is deliberate: there the un-costed item was a fabric, here it is a control plane. Both are the thing the new architecture needs and the old one did not, and both fall outside the boundary of the report that justifies the change.

14. RTL 10 — Composable Infrastructure Assembled

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// RTL 10 - composable infrastructure assembled. Everything that must hold before
// composing a machine beats buying one that already fits.
module composable_model #(parameter int ASSEMBLED_ONLY = 0) (
  input  logic clk, rst_n,
  input  logic       evaluate,
  input  logic       servers_composed,     // machines are assembled, not bought
  input  logic       ratio_fit_improved,   // the strand from the SKU ratio is gone
  input  logic       inventory_sufficient, // every resource type is checked
  input  logic       latency_budgeted,     // bind time is in the start-up budget
  input  logic       generations_matched,  // no machine spans generations
  input  logic       control_plane_sized,  // the fabric manager keeps up
  output logic       improves,
  output logic [5:0] fail_mask,
  output logic [7:0] n_eval, n_improves,
  output logic       false_gain_err
);
  assign fail_mask[0] = ~servers_composed;
  assign fail_mask[1] = ~ratio_fit_improved;
  assign fail_mask[2] = ~inventory_sufficient;
  assign fail_mask[3] = ~latency_budgeted;
  assign fail_mask[4] = ~generations_matched;
  assign fail_mask[5] = ~control_plane_sized;
  // The assembled-only build reports that machines are being composed, which is
  // the number a composability programme is measured on.
  assign improves = (ASSEMBLED_ONLY != 0) ? servers_composed : (fail_mask == 6'd0);
  assign false_gain_err = evaluate && improves && (fail_mask != 6'd0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      n_eval <= 8'd0; n_improves <= 8'd0;
    end else if (evaluate) begin
      n_eval <= n_eval + 8'd1;
      if (improves) n_improves <= n_improves + 8'd1;
    end
  end
endmodule
ConfigurationFail mask · Full model · Assembled-only model
everything holds000000 · improves · improves
the SKU strand was never removed000010 · does not improve · improves
plus the inventory and the bind latency001110 · does not improve · improves
only the generations are mixed010000 · does not improve · improves
only the control plane is undersized100000 · does not improve · improves
nothing was composed000001 · does not improve · does not improve

One improving configuration of six, and four false claims.

The assembled-only definition is the metric a composability programme is measured on — machines composed, as a count or a percentage — and it is right about one of the six. Row two is the purest form: the fabric works, machines are assembled, and the assembled ratios are the SKU ratios because nobody changed the request templates.

A flowchart deciding whether a workload should be composed or bought. If a fixed SKU already fits the workload's ratio, buy it. If instances are shorter than the bind overhead can amortise, buy. If the request needs more of a resource than any single fabric domain holds, buy. If the fleet's instance start rate exceeds the control plane's compose rate, buy. Otherwise compose.yesnonoyesnoyesyesnoa workload to placea SKU fits theratio?instance over 3min?fits onedomain?control planekeeps up?buy the SKUtoo short to composeno domain can holditcompose it

Figure 4 — Four exits and one composes. The first question is the one that decides most cases and is asked least: a workload whose ratio a stock SKU already serves has nothing to gain, and the composability programme's own metric counts composing it as a success.

15. Quantitative Reasoning

SKU rigidity. An 8-core, 128 GB SKU serving 8 cores and 512 GB buys four servers, 32 cores, and strands 24 — 75%. At 1024 GB it strands 56 of 64, or 87%.

Compose fit. A pool of 64 cores, 1024 GB and eight accelerators: a request short only on accelerators is refused by a full check and accepted by a CPU-only one.

Bind latency. Four binds at 250 ms on an 8-second boot is 12%; sixteen binds is 50%, and eight is exactly the 25% threshold.

Fragmentation. 512 GB free with no domain above 128 refuses a 256 GB request — and refuses a 512 GB request that reads as an exact fit.

Instance lifetime. Eighteen seconds of bind and teardown is 6% of a five-minute instance and 30% of a one-minute one; three minutes is exactly the 10% threshold.

Generations. An 800 Gbps part and a 400 Gbps part make a 400 Gbps machine — a 50% loss against the fastest part in the pool.

Reliability. Four parts each lasting a year make a 2190-hour machine failing four times a year; eight parts make it six weeks.

Control plane. 120 composes a minute demanded of a manager tracking 60 leaves half the demand queued.

Cost. 9120 per hundred workloads composed against 10,000 fixed — and break-even at an orchestration layer costing 1152, which is 29% of the fixed-rack spend.

The assembled model. Six properties, six configurations, one improves. The assembled-only definition reported five.

QuantityCorrect · Broken · Ratio
Cores stranded, 8 wanted and 512 GB24 of 32 · 0 reported · all of it
Composes refused, 6 attempted3 · 2 · the accelerator case
Start-up overhead, 16 binds50% · 0 reported · the whole bind
Usable by one machine, 512 GB free128 GB · 512 offered · 4x
Bind share of a one-minute instance30% · 0 reported · all of it
Machine rate, an 800 and a 400 part400 Gbps · 800 claimed · 2x
Machine MTBF, four year-long parts2190 h · 8760 claimed · 4x
Composes served of 120 demanded60 · 120 promised · 2x
Cost per hundred workloads9120 · 7120 claimed · the control plane
Configurations called improving, of 61 · 5 · 4 false claims

16. Assertions

Every check is an explicit comparison against an exact value. Icarus Verilog 13.0 has no concurrent assertion support, so each is a procedural comparison against 1'b1, and every one is an equality.

Every inclusive threshold in this chapter is driven at exactly equal, constructed rather than swept — the batch-021 carry-forward, kept.

SKU rigidity. A strand of exactly 25% is constructed from a 24-core need against 512 GB, and both non-multiple cases are driven — nine cores and 500 GB.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
chk(kGs == 16'd2,  "nine cores need two SKUs, not one");
chk(kGt == 16'd7,  "stranding seven");

Compose fit. A request that exactly empties the pool is driven, and the cores-short case is asserted as one the CPU-only model gets right.

Bind latency. An overhead of exactly 25% is constructed from eight binds, and the unmeasured-boot case is asserted to report added milliseconds without a ratio.

Fragmentation. A request exactly the size of the largest domain is driven, and the request that "exactly fits" the sum is asserted unbuildable.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
chk(rGs == 1'b0, "512 GB does not fit a 128 GB domain");
chk(rBs == 1'b1, "though the whole-pool model thinks it exactly fits");

Instance lifetime. An overhead of exactly 10% is constructed from a three-minute life, and the instant-bind case is asserted as not a hidden cost.

Generations. The mix is driven both ways round, and a loss of exactly 20% is constructed from an 800 and a 640 part.

Reliability. Exactly two parts is driven at the acceptance threshold, and the case where the part count exceeds a part's life in hours is asserted unbounded.

Control plane. Demand exactly at capacity is driven.

Cost. The orchestration cost at which the two are exactly equal is constructed, and asserted not cheaper.

The assembled model. Every fail mask is asserted as an exact six-bit value, and each of the six bits is driven false alone.

Totals: 279 checks across two testbenches, 145 on the front five models and 134 on the back five, all passing on the unmutated sources.

17. Mutation Testing

Sixty-three mutations were injected one at a time. 63 injected, 63 killed, after two survivors.

Model · MutationVerdict
1 · the server count follows the cores onlykilled
1 · the core ceiling rounds downkilled
1 · the memory ceiling rounds downkilled
1 · the ratio is assumed to match in both buildskilled
1 · the strand share divides by what was neededkilled
1 · the balance threshold becomes exclusivekilled
1 · the hidden-strand check drops the over-provision guardkilled
2 · the memory check becomes exclusivekilled
2 · the accelerator type is not checkedkilled
2 · only the cores are checked in both buildskilled
2 · the worst shortfall ignores the acceleratorskilled
2 · the short-type count drops the memory termkilled
2 · the partial-check test ignores the short typeskilled
3 · the resource count is droppedkilled
3 · composing is instant in both buildskilled
3 · the added time is the whole composekilled
3 · the overhead divides by the composekilled
3 · the acceptance threshold becomes exclusivekilled
3 · the ignored-bind check drops the zero-cost guardkilled
3 · the unmeasured-boot guard is removedkilled
4 · the whole pool is offered in both buildskilled
4 · the fragmented amount is counted from the wrong sidekilled
4 · the satisfiability test becomes exclusivekilled
4 · the ignored-fragmentation check drops the domain testkilled
5 · the teardown is not countedkilled
5 · the bind is free in both buildskilled
5 · the life is read in minutes, not secondskilled
5 · the overhead share divides the wrong waykilled
5 · the acceptance threshold becomes exclusivekilled
5 · the free-bind check drops the compose guardkilled
5 · the unstated-lifetime guard is removedkilled
6 · the fastest part is taken in both buildskilled
6 · an unmixed machine takes the slowest part tookilled
6 · the fastest and slowest are swappedkilled
6 · the loss share divides by the effective ratekilled
6 · the acceptance threshold becomes exclusivekilled
6 · the uniform check drops the differing-rate guardkilled
6 · the unmeasured-rate guard is removedkilled
7 · the part count does not divide the reliabilitykilled
7 · the chassis is blamed in both buildskilled
7 · the yearly failure count divides the wrong waykilled
7 · the acceptance threshold becomes exclusivekilled
7 · the ignored-parts check drops the part-count guardkilled
7 · the zero-reliability guard is removedkilled
8 · everything demanded is served in both buildskilled
8 · the served rate is not capped by the capacitykilled
8 · the backlog is counted from the wrong sidekilled
8 · the keeps-up test is invertedkilled
8 · the ignored-control check drops the over-demand guardkilled
8 · the no-demand guard is removedkilled
9 · the orchestration is left out in both buildskilled
9 · the fixed cost per workload uses the wrong scalekilled
9 · the comparison is the wrong way roundkilled
9 · the comparison becomes inclusivekilled
9 · the ignored-orchestration check drops the cost guardkilled
9 · the no-workload guard is removedkilled
10 · ratio-fit bit dropped from the maskkilled
10 · inventory bit dropped from the maskkilled
10 · bind-latency bit dropped from the maskkilled
10 · generation bit dropped from the maskkilled
10 · control-plane bit dropped from the maskkilled
10 · any-property instead of every-propertykilled
10 · false-gain check ignores the maskkilled

Both survivors were the same omission and it is a new class. Section 5's two ceilings — cores per SKU and gigabytes per SKU — both survived being changed to floors, because every need in the testbench was an exact multiple of its SKU dimension. Eight cores into an 8-core SKU, 512 GB into a 128 GB SKU: ceil and floor agree on every one, so the mutation changed nothing observable.

This is the equality-case gap in a different costume, and that is the finding. Batch 021's survivors were thresholds never driven at the boundary; these are ceilings never driven off the boundary. The rule that catches both is the same one stated more generally: for any operation whose whole purpose is to handle a special case, drive the special case and drive its complement. A <= needs the equality; a ceil needs the remainder.

Constructing the kills needed a case where the rounded resource also binds. Nine cores against 128 GB — the cores bind and nine is not a multiple of eight — kills the core ceiling. Eight cores against 500 GB — the memory binds and 500 is not a multiple of 128 — kills the memory one. A remainder on the resource that does not bind changes nothing, which is why the first attempt at each case failed to kill.

The complete set was re-run after the stimulus change, per standing discipline, and all sixty-three held.

18. Verification Strategy

What a testbench for a composition model must cover.

Drive the special case and its complement. A threshold needs its equality; a ceiling needs its remainder; a minimum needs both operands to win. This chapter's only survivors were the second of those, and the general rule now covers all three.

Make the rounded quantity the binding one. A remainder on a resource that does not decide the answer is invisible. Both survivors needed not just a non-multiple but a non-multiple that binds, which took two attempts to construct.

Drive symmetric operands both ways. Section 10's generation mix is tested with the slow part first and the slow part second, because 21.4 established that reasoning about symmetry is not the same as testing it.

The cases where the fixed-SKU model is right. A workload matching the SKU ratio. Cores as the binding resource for a CPU-only scheduler. One domain holding everything. An hour-long instance. Parts of one generation. A single-part machine. Six cases where the broken build is correct, each exempted explicitly.

Counters as a second signature. Ten models, ten pairs of totals, and the builds differ in all ten — four rigid against none, three failed against two, three fragile against none.

What a real composable system needs that these models do not have. Time and correlation. Fragmentation accumulates; generations drift as the pool refreshes; compose demand spikes when an autoscaler reacts to the same event across a fleet. Every model here is a snapshot, and section 26 exercise 9 is the closest this chapter comes to the dynamics.

19. Synthesis and Implementation Reality

Section 5's arithmetic is a purchasing model, and it is the only part of this chapter that runs before any hardware exists. Its failure mode is a rack order.

Section 6's inventory check lives in the scheduler, and the practical difficulty is that the scheduler and the fabric manager are usually different systems with different views. A conjunction across three inventories held in two places is where the check gets simplified, which is exactly how the broken build arises.

Section 7's bind time is fabric-manager and firmware together. Enumerating a newly attached device is a PCIe and CXL discovery sequence, and its cost is real silicon and real firmware — 21.1 is where the mechanism lives. Binding in parallel is the available optimisation and it is not free, because discovery order matters for some device classes.

Section 8's domains are cabling. Which resources a given host can reach is fixed by the fabric topology at build time, and no software changes it — the same irreversibility 23.1 §19 identified for hop count.

Section 10's generation mixing is an allocator policy and the cheapest of the six to fix: refuse to span generations, at the cost of more fragmentation in section 8's terms. The two policies trade directly against each other.

Section 12's control plane is a distributed system with a database, and its compose rate is a throughput number like any other. It is also a single point of failure for fleet growth, which is a property no fixed-SKU rack had.

20. Silicon Observability

CounterWhy it matters
Requested against provisioned, per resource type, per machineSection 5's strand, which is the entire justification
Compose attempts, and refusals by which resource type was shortSection 6 — the type matters more than the count
Bind time per resource, and total compose timeSection 7's overhead, measured rather than specified
Instance lifetime distributionSection 9 — the amortisation is a workload property
Free capacity per fabric domain, not summedSection 8 — the sum is the wrong statistic
Generation of every part in every composed machineSection 10, which is otherwise invisible until a benchmark
Parts per composed machineSection 11's series reliability, before the outage
Outages by which borrowed part failedSection 11 measured rather than modelled
Compose demand and control-plane service rateSection 12's queue
Composes counted against composes that improved the fitSection 14 — the metric against the thing it stands for

"Free capacity per fabric domain, not summed" is the counter that has to replace one that already exists. Every capacity dashboard reports a total, and section 8 shows the total is unusable for a compose decision. This is harder than adding a counter, because the existing number is not obviously wrong — it is correct about the fleet and wrong about any single machine.

21. Debug Lab

Symptom. A team moves a batch-processing fleet to composed machines. The programme reports 94% of instances composed — its headline metric, met. Three months later: instance start latency is up 60%, one service in five reports intermittently halved throughput, machine outages have tripled, and during traffic spikes new instances stop being created for minutes at a time.

Step 1 — did the fit actually improve? Requested against provisioned, per resource type: the composed machines have the same ratios as the SKUs they replaced. The request templates were copied from the old instance types, so section 5's strand was carried across intact. The headline metric is true and the thing it was standing for did not happen.

Step 2 — the start latency. Bind time per resource: 250 ms, and the composed machines bind sixteen resources because the templates enumerate every device individually. Section 7 exactly: a 50% start-up overhead, on a boot that was already the fleet's biggest complaint.

Step 3 — and the instances are short. Lifetime distribution: median 90 seconds. Eighteen seconds of bind and teardown against a 90-second life is 20% — section 9, twice the acceptable threshold, and the fleet is spending a fifth of its machine-time assembling machines.

Step 4 — the halved throughput. Generation of every part, per machine: 19% of machines span two generations, and those are the ones reporting half rate. Section 10, and the allocator has no generation constraint because nothing asked for one.

Step 5 — the outages. Parts per machine: sixteen. At a one-year part life that is a 548-hour composite MTBF — an outage every three weeks per machine, against the old sealed server's yearly one. Section 11, and the tripling is if anything an under-count.

Step 6 — the spikes. Compose demand against control-plane service rate: demand peaks at 210 a minute against a manager sized for 60. Section 12, and the autoscaler's reaction to a traffic spike is precisely the event that generates a synchronised compose burst.

The finding. Five distinct failures, all predicted by this chapter, and the programme's own metric improved throughout. The root cause of the first is the one that makes the rest worse: copying the old instance templates preserved both the ratios and the sixteen-device enumeration, which drove the bind count, the compose rate and the parts count simultaneously.

The fix, in the order the numbers say. Rewrite the templates to request what the workloads actually need — which fixes section 5, and reduces the parts count, which improves sections 7, 11 and 12 at once. Add a generation constraint to the allocator. And move the 90-second workloads back to pre-composed machines, because section 9's arithmetic says they cannot amortise a bind at any parts count.

What made this hard. Nothing failed. The fabric worked, the fabric manager worked, every machine composed successfully, and the metric the programme was accountable for went up and stayed up. Five of the six counters that would have shown the problem are ones a fixed-SKU fleet had no reason to collect.

22. Design Review

1. Does a stock SKU already fit this workload's ratio? If it does, composing it is a metric, not a gain. Section 5.

2. What is the strand, per resource type, before and after? The programme's actual objective, and section 21 is what happens when nobody measures it.

3. Does the scheduler check every resource type, or the one it grew up checking? Section 6.

4. How many resources does a machine bind, and at what cost each? Bind time is linear in parts. Section 7.

5. What is the instance lifetime distribution? Below three minutes, composability costs more than it saves. Section 9.

6. Is free capacity reported per domain or summed? A compose needs a maximum, not a sum. Section 8.

7. Can a machine span generations, and does anything stop it? A 50% rate loss with nothing broken. Section 10.

8. How many borrowed parts, and what is the composite MTBF? Reliability divides. Section 11.

9. What is the peak compose rate, and what does the fabric manager serve? An autoscaler makes these synchronised. Section 12.

10. What does the orchestration layer cost, against the fixed-rack spend it replaces? Break-even is 29%. Section 13.

23. How This Appears In Real Engineering

A platform team running a composability programme owns section 5 and usually measures section 14 instead. The two are different questions and only one of them is the objective — "machines composed" is easy to count and "strand removed" is what was promised, and section 21 is a fleet where the first hit 94% and the second never moved.

A scheduler team owns section 6, and the difficulty is architectural rather than careless. Resource inventories for cores, memory and accelerators are frequently held by different systems, so a conjunction across all three is a distributed query on the hot path of every placement. Simplifying it to the one inventory the scheduler owns is the natural engineering response and the exact defect.

A reliability function meets section 11 as a step change, exactly as 23.1 §23 describes for blast radius. A bought server's MTBF was a vendor number; a composed machine's is a series calculation the organisation now owns, and there is rarely anyone whose job it was to notice the transfer.

A capacity or finance function owns section 13, and the reporting boundary is the problem again. The resource saving is a hardware line and the orchestration layer is a software and headcount line, so the comparison that decides the architecture spans two budgets that no single report covers.

24. Common Misconceptions

"A composable machine is just a server you configure." It is a server whose parts are in series and whose reliability divides by their count. Section 11.

"Composability removes waste." It removes the SKU-ratio strand, if the request templates change. Sections 5 and 21.

"The scheduler will find a machine that fits." It will find one that fits on the resource it checks. Section 6.

"Boot time is boot time." Sixteen binds add half the boot again. Section 7.

"We have 512 GB free." No single machine can have more than 128 of it. Section 8.

"Composing is cheap once it works." Eighteen seconds is 30% of a one-minute instance. Section 9.

"The pool is the pool." It holds three generations, and a machine runs at the oldest part it was given. Section 10.

"Our parts are enterprise-grade." Four year-long parts make a quarter-year machine. Section 11.

"The fabric manager is control-plane software." It is a throughput bottleneck on every instance start, and a single point of failure for fleet growth. Section 12.

"94% of instances are composed." One property of six. Section 14.

25. Interview Reasoning

Q. What does composability actually buy?

The removal of the SKU-ratio strand. A workload needing eight cores and 512 GB on an 8-core, 128 GB SKU buys four servers and strands 24 of 32 cores — 75%, and no packing fixes it because the ratio is soldered. Composing takes eight cores and 512 GB from two pools with nothing over-bought.

Q. What does it cost that a fixed SKU did not?

Five things. Bind time on every start, linear in the parts count. Fragmentation, because a compose draws from one fabric domain and a dashboard reports a sum. Generation mixing, because a pool refreshes incrementally. Series reliability, because the machine fails when any borrowed part does. And a control plane that is a rate limit on instance creation. Four of those five are new ways to fail, not worse versions of old ones.

Q. Why does a composed machine fail more often than the server it replaced?

Because it is four or eight things in series instead of one sealed unit. Four parts each lasting a year make a 2190-hour machine — four outages annually instead of one — and no part is defective. A per-part reliability review passes and the machine still does not stay up.

Q. Your fleet has 512 GB free and a 256 GB request fails. Explain.

The 512 is a sum across fabric domains and a machine draws from one. If no domain holds more than 128, the largest composable allocation is 128 — the capacity is free, idle, and unreachable from the host that wants it. The fix is a per-domain counter, which means replacing a dashboard number rather than adding one.

Q. When is composability the wrong answer?

When the instances are short. Eighteen seconds of bind and teardown is 6% of a five-minute instance and 30% of a one-minute one — so below about three minutes it costs more than the strand it recovers. The workloads composability is most often pitched at, short-lived and bursty, are the ones it suits worst.

Q. Your programme reports 94% of instances composed and everything got worse. Where do you look?

At requested-against-provisioned per resource type. If the request templates were copied from the old instance types, the composed machines have the SKU ratios and the strand never moved — the metric measures the mechanism rather than the objective. That one finding also explains a high parts count, which drives the bind time, the compose rate and the failure rate together.

26. Exercises

1. Extend RTL 1 to report the memory strand as well as the core strand, and show that every unbalanced workload strands exactly one of them.

2. Give RTL 2 a fourth resource type and show that the probability of a partial check being wrong grows with the type count.

3. Make RTL 3's binds parallel with a fixed concurrency and find the concurrency at which sixteen resources become acceptable.

4. Drive RTL 4 with a domain-size distribution and compute the largest request that succeeds 99% of the time.

5. Combine RTL 5 and RTL 3: for a given lifetime distribution, find the parts count above which composing loses.

6. Add a generation-matching constraint to RTL 6 and show what it costs in RTL 4's terms.

7. Extend RTL 7 to parts with different lifetimes and find which part dominates the composite.

8. Make RTL 8's demand bursty rather than steady and find the control-plane capacity that bounds the queue.

9. Model section 21 end to end: templates copied, parts count high, generations mixed, and the compose burst during a spike.

10. Add a seventh property to RTL 10. If it is implied by one of the six, say which; if not, give the fleet it catches that the current mask calls improving.

27. Summary

23.1 pooled one resource and priced six costs. This chapter assembles a machine from several pools, and the shape of the answer is the same with the ratio changed: one clean gain, and five costs of which four are new failure modes.

A fixed SKU has a ratio and strands whatever it over-buys. Eight cores and 512 GB on an 8-core, 128 GB SKU buys 32 cores and strands 24 — 75% — and at 1024 GB it strands 87%.

Composing is a conjunction and a scheduler is usually a CPU scheduler. A machine short only on accelerators does not compose, and a CPU-only check finds nothing wrong.

Bind time is linear in the parts count, which is the variable composability frees. Four binds cost 12% of an 8-second boot; sixteen cost 50%, and eight is exactly the threshold.

Free capacity is not composable capacity. 512 GB free with no domain above 128 refuses a 256 GB request — and a 512 GB request that reads as an exact fit is a machine that cannot be built anywhere.

Short instances pay the bind in full. Eighteen seconds is 6% of five minutes and 30% of one — so composability has a minimum useful instance duration of about three minutes, and short bursty workloads are the ones it suits worst.

A pool holds generations. An 800 Gbps part and a 400 Gbps part make a 400 Gbps machine, and the allocator has no reason to refuse unless something tells it to.

Reliability divides by the parts. Four parts each lasting a year make a 2190-hour machine failing four times annually — and every part passes its own review.

The control plane is a rate limit on fleet growth. 120 composes a minute demanded of a manager tracking 60 queues half of them, and an autoscaler is exactly what makes the demand synchronised.

The orchestration layer is the un-costed item. 9120 per hundred workloads against 10,000 fixed — break-even at an orchestration cost of 29% of the fixed-rack spend, which is one ratio available before anything is bought.

Two mutations survived because every need was an exact multiple of its SKU. Ceilings and floors agreed everywhere, so the rounding was untested — the equality-case gap in a new costume, and the rule that catches both is to drive a special case and its complement.

Composing machines is one property of six. The metric a composability programme is measured on called five of six fleets improved when one was — and section 21 is a fleet that hit 94% composed while its strand never moved at all.

23.3 — Resource Utilisation takes the measurement problem that has now appeared twice, in 23.1 §14 and here, and makes it the subject: what a utilisation number actually says, what it cannot say, and how to build one that means what a capacity plan needs it to mean.

Continue learning

Standards & specifications

Governing standard
CXL Specification (CXL Consortium)(opens CXL Consortium in a new tab)

Defines CXL.io, CXL.cache and CXL.mem, and the coherence and memory-pooling behaviour built on them. System design and deployment topology are not mandated.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the CXL curriculum.