Skip to content

Instantly share code, notes, and snippets.

@sinkers
Created April 15, 2026 09:56
Show Gist options
  • Select an option

  • Save sinkers/35324b66b5bd1c6e8f3631c2bf675f51 to your computer and use it in GitHub Desktop.

Select an option

Save sinkers/35324b66b5bd1c6e8f3631c2bf675f51 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Inference Data Center — Cost per MW Calculator</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&family=DM+Sans:wght@400;500&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0f1117;
--surface: #181c27;
--surface2: #1f2436;
--border: rgba(255,255,255,0.08);
--border2: rgba(255,255,255,0.14);
--text: #e8eaf0;
--muted: #8b90a0;
--accent: #f5a623;
--accent-dim: rgba(245,166,35,0.12);
--blue: #4a90d9;
--green: #3ecf8e;
--red: #f56565;
--mono: 'IBM Plex Mono', monospace;
--sans: 'DM Sans', sans-serif;
--display: 'Syne', sans-serif;
--radius: 8px;
--radius-lg: 12px;
}
html { font-size: 15px; }
body { background: var(--bg); color: var(--text); font-family: var(--sans); min-height: 100vh; padding: 0; }
/* ── Header ── */
header {
padding: 48px 48px 32px;
border-bottom: 1px solid var(--border);
position: relative;
overflow: hidden;
}
header::before {
content: '';
position: absolute;
top: -60px; right: -60px;
width: 320px; height: 320px;
border-radius: 50%;
background: radial-gradient(circle, rgba(245,166,35,0.06) 0%, transparent 70%);
pointer-events: none;
}
.header-tag {
font-family: var(--mono);
font-size: 11px;
color: var(--accent);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 12px;
}
h1 {
font-family: var(--display);
font-size: 32px;
font-weight: 700;
color: #fff;
line-height: 1.15;
max-width: 680px;
margin-bottom: 12px;
}
.header-desc {
font-size: 14px;
color: var(--muted);
max-width: 640px;
line-height: 1.6;
}
.header-meta {
margin-top: 16px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.meta-item {
font-family: var(--mono);
font-size: 11px;
color: var(--muted);
padding: 4px 10px;
border: 1px solid var(--border2);
border-radius: 20px;
}
/* ── Main layout ── */
main { padding: 40px 48px; max-width: 1200px; }
/* ── Slider ── */
.controls { margin-bottom: 32px; }
.control-label {
font-family: var(--display);
font-size: 13px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 12px;
}
.slider-row { display: flex; align-items: center; gap: 20px; }
input[type=range] {
flex: 1;
-webkit-appearance: none;
height: 3px;
border-radius: 2px;
background: var(--border2);
outline: none;
cursor: pointer;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px; height: 20px;
border-radius: 50%;
background: var(--accent);
cursor: pointer;
box-shadow: 0 0 0 4px rgba(245,166,35,0.2);
transition: box-shadow 0.15s;
}
input[type=range]::-webkit-slider-thumb:hover { box-shadow: 0 0 0 6px rgba(245,166,35,0.25); }
.slider-val {
font-family: var(--mono);
font-size: 22px;
font-weight: 500;
color: var(--accent);
min-width: 80px;
text-align: right;
}
/* ── Metrics ── */
.metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 36px; }
.metric {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 20px 22px;
}
.metric-label { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.metric-val {
font-family: var(--mono);
font-size: 26px;
font-weight: 500;
color: #fff;
line-height: 1;
margin-bottom: 4px;
}
.metric-sub { font-size: 12px; color: var(--muted); }
.metric-sub.positive { color: var(--green); }
/* ── Table ── */
.table-wrap { width: 100%; overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
thead th {
font-family: var(--mono);
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
padding: 0 12px 10px;
border-bottom: 1px solid var(--border2);
text-align: right;
white-space: nowrap;
}
thead th:first-child { text-align: left; }
.group-row td {
font-family: var(--display);
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
background: var(--surface2);
padding: 10px 12px;
border-top: 1px solid var(--border);
}
tbody tr.data-row {
border-bottom: 1px solid var(--border);
cursor: pointer;
position: relative;
transition: background 0.12s;
}
tbody tr.data-row:hover { background: rgba(255,255,255,0.03); }
tbody tr.data-row.active { background: var(--accent-dim); }
td {
padding: 13px 12px;
font-size: 13px;
vertical-align: middle;
text-align: right;
color: var(--text);
white-space: nowrap;
}
td:first-child { text-align: left; white-space: normal; }
.cat-name { font-size: 13px; color: var(--text); display: flex; align-items: center; gap: 8px; }
.cat-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.mono { font-family: var(--mono); font-size: 12px; }
.saving-val { font-family: var(--mono); font-size: 12px; color: var(--green); }
.saving-none { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.scale-badge {
display: inline-block;
font-size: 10px;
font-family: var(--mono);
padding: 3px 8px;
border-radius: 20px;
white-space: nowrap;
}
.hint-icon {
display: inline-flex; align-items: center; justify-content: center;
width: 16px; height: 16px;
border: 1px solid var(--border2);
border-radius: 50%;
font-size: 10px;
color: var(--muted);
flex-shrink: 0;
margin-left: 4px;
font-family: var(--sans);
user-select: none;
}
.total-row td {
font-family: var(--mono);
font-weight: 500;
font-size: 13px;
border-top: 1px solid var(--border2);
padding-top: 14px;
}
.total-row td:first-child { font-family: var(--display); font-weight: 600; font-size: 13px; color: #fff; }
/* ── Popover ── */
.popover-overlay {
display: none;
position: fixed;
inset: 0;
z-index: 99;
}
.popover {
display: none;
position: fixed;
z-index: 100;
width: 420px;
background: #1a1f2e;
border: 1px solid var(--border2);
border-radius: var(--radius-lg);
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
overflow: hidden;
pointer-events: all;
}
.popover.visible { display: block; }
.popover-overlay.visible { display: block; }
.pop-header {
padding: 16px 18px 14px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: flex-start;
gap: 10px;
}
.pop-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; margin-top: 4px; }
.pop-title { font-family: var(--display); font-weight: 600; font-size: 14px; color: #fff; margin-bottom: 3px; }
.pop-desc { font-size: 12px; color: var(--muted); line-height: 1.5; }
.pop-close {
margin-left: auto;
background: none;
border: none;
color: var(--muted);
font-size: 18px;
cursor: pointer;
line-height: 1;
padding: 2px 4px;
flex-shrink: 0;
}
.pop-close:hover { color: var(--text); }
.pop-body { padding: 14px 18px; }
.pop-section { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 8px; }
.pop-items { margin-bottom: 14px; }
.pop-item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 8px 0;
border-bottom: 1px solid var(--border);
}
.pop-item:last-child { border-bottom: none; }
.pop-item-left { flex: 1; }
.pop-item-name { font-size: 12px; color: var(--text); margin-bottom: 2px; }
.pop-item-note { font-size: 11px; color: var(--muted); line-height: 1.4; }
.pop-item-right { text-align: right; flex-shrink: 0; }
.pop-item-cost { font-family: var(--mono); font-size: 12px; color: var(--accent); }
.pop-item-pct { font-family: var(--mono); font-size: 10px; color: var(--muted); }
.pop-refs { background: rgba(255,255,255,0.03); border-radius: var(--radius); padding: 10px 12px; margin-top: 4px; }
.pop-ref-title { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin-bottom: 6px; }
.pop-ref-item { font-size: 11px; color: var(--muted); margin-bottom: 4px; padding-left: 10px; position: relative; line-height: 1.4; }
.pop-ref-item::before { content: '›'; position: absolute; left: 0; color: var(--accent); }
.pop-bar-wrap { height: 3px; background: var(--border); border-radius: 2px; margin-top: 4px; overflow: hidden; }
.pop-bar { height: 100%; border-radius: 2px; }
.pop-cost-at { font-size: 11px; color: var(--muted); padding: 10px 18px 4px; border-top: 1px solid var(--border); font-family: var(--mono); }
/* ── Chart ── */
.chart-section { margin-top: 48px; }
.section-title {
font-family: var(--display);
font-size: 16px;
font-weight: 600;
color: #fff;
margin-bottom: 6px;
}
.section-sub { font-size: 13px; color: var(--muted); margin-bottom: 22px; }
.chart-box {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 24px;
position: relative;
height: 280px;
}
canvas { display: block; }
/* ── References ── */
.refs-section {
margin-top: 40px;
padding-top: 32px;
border-top: 1px solid var(--border);
}
.refs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.ref-group { }
.ref-group-title { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent); margin-bottom: 10px; }
.ref-entry { font-size: 12px; color: var(--muted); margin-bottom: 8px; line-height: 1.5; padding-left: 12px; position: relative; }
.ref-entry::before { content: '—'; position: absolute; left: 0; color: var(--border2); }
/* ── Footer ── */
footer {
margin-top: 48px;
padding: 24px 48px;
border-top: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 12px;
}
.footer-note { font-size: 12px; color: var(--muted); }
.footer-tag { font-family: var(--mono); font-size: 11px; color: var(--border2); }
@media (max-width: 760px) {
header, main, footer { padding-left: 20px; padding-right: 20px; }
h1 { font-size: 24px; }
.metrics { grid-template-columns: 1fr; }
.popover { width: calc(100vw - 32px); left: 16px !important; right: 16px !important; }
.refs-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header>
<div class="header-tag">Capital Expenditure Model · 2026</div>
<h1>AI Inference Data Center<br>Cost per Megawatt Calculator</h1>
<p class="header-desc">
All-in construction and equipment costs for a purpose-built AI inference facility, including
GPU hardware, liquid cooling, networking, and civil infrastructure. Hover or click any row
for a detailed sub-component breakdown and source references.
</p>
<div class="header-meta">
<span class="meta-item">Baseline: $35–45M / MW</span>
<span class="meta-item">Midpoint: $40M / MW at 1 MW</span>
<span class="meta-item">Scale: 1 – 200 MW</span>
<span class="meta-item">Updated: April 2026</span>
</div>
</header>
<main>
<div class="controls">
<div class="control-label">Facility capacity</div>
<div class="slider-row">
<input type="range" min="1" max="200" value="1" step="1" id="mw-slider">
<div class="slider-val"><span id="mw-display">1</span> MW</div>
</div>
</div>
<div class="metrics">
<div class="metric">
<div class="metric-label">Total capital expenditure</div>
<div class="metric-val" id="total-cost">$40.0M</div>
<div class="metric-sub" id="total-sub">at 1 MW</div>
</div>
<div class="metric">
<div class="metric-label">Blended cost per MW</div>
<div class="metric-val" id="per-mw">$40.0M</div>
<div class="metric-sub" id="per-mw-sub">1 MW baseline</div>
</div>
<div class="metric">
<div class="metric-label">Infrastructure savings vs linear</div>
<div class="metric-val" id="saving-val">—</div>
<div class="metric-sub positive" id="saving-sub">economies of scale</div>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th style="text-align:left; min-width:240px;">Category</th>
<th>Base (1 MW)</th>
<th>Total at N MW</th>
<th>Cost / MW</th>
<th>Saving vs linear</th>
<th style="text-align:left; min-width:150px;">Scaling behaviour</th>
</tr>
</thead>
<tbody id="table-body"></tbody>
</table>
</div>
<div class="chart-section">
<div class="section-title">Blended cost/MW as facility scales</div>
<div class="section-sub">Infrastructure economies of scale reduce the all-in cost per MW — but GPU hardware prevents it falling below ~$22M at any realistic scale.</div>
<div class="chart-box">
<canvas id="curve-chart"></canvas>
</div>
</div>
<div class="refs-section">
<div class="section-title" style="margin-bottom:20px;">Primary sources & methodology</div>
<div class="refs-grid">
<div class="ref-group">
<div class="ref-group-title">Construction costs</div>
<div class="ref-entry">JLL Global Data Center Outlook 2026 — shell &amp; core average global cost forecast $11.3M/MW; AI fit-out up to $25M/MW (March 2026)</div>
<div class="ref-entry">Turner &amp; Townsend Data Centre Construction Cost Index 2025–2026 — campus scale $45–55B/GW fully built-out</div>
<div class="ref-entry">ConstructConnect 2025 — average cost per sq ft surpassed $1,033 by year-end 2025, up from $535 in 2023</div>
<div class="ref-entry">ConstructElements — AI-optimised build cost modelling, February 2026</div>
</div>
<div class="ref-group">
<div class="ref-group-title">IT equipment & hardware</div>
<div class="ref-entry">Bernstein Research — GB200/NVL72 rack at $5.9M ($3.4M compute + $2.5M infra); GPUs = 39% of total AI DC capex, November 2025</div>
<div class="ref-entry">NVIDIA FY Q2 2026 earnings call — $50–60B per GW campus cost estimate</div>
<div class="ref-entry">Thunder Said Energy — AI data center economics model; total capex ~$40M/kW ($40M/MW) for GPU-heavy builds, November 2025</div>
<div class="ref-entry">Avid Solutions — 2026 global data center growth projections, January 2026</div>
</div>
<div class="ref-group">
<div class="ref-group-title">Cooling & power infrastructure</div>
<div class="ref-entry">GPUnex Blog — liquid cooling adds $500K–$2M/MW capex; AI racks exceed 50 kW/rack by 2026, February 2026</div>
<div class="ref-entry">mlq.ai — CDU market growing at 33% CAGR; integrated solutions reach $2–3M/MW, December 2025</div>
<div class="ref-entry">IoT Analytics — Data Centre Equipment &amp; Infrastructure Market Report 2025–2030; modern AI racks exceeding 100 kW/rack, November 2025</div>
<div class="ref-entry">Schneider Electric Galaxy VXL UPS launch (April 2025); ABB MegaFlex AI-ready architecture (July 2025)</div>
</div>
<div class="ref-group">
<div class="ref-group-title">Market context</div>
<div class="ref-entry">McKinsey — The cost of compute: $7 trillion race to scale data centers; $3.1T allocated to chip/hardware vendors, April 2025</div>
<div class="ref-entry">Alpha Matica — Deconstructing the Data Center: total investment $3.4B–$5.5B+ for 100 MW AI facility, January 2026</div>
<div class="ref-entry">Shield Operations — AI data center power consumption; B200 at 1,000W, 100,000 GPU cluster = 87.5 MW compute load, February 2026</div>
<div class="ref-entry"><em>Scaling exponents are modelled estimates based on industry benchmarks. Actual curves vary significantly by region, redundancy class, and procurement strategy.</em></div>
</div>
</div>
</div>
</main>
<footer>
<div class="footer-note">Costs reflect US market mid-range. Europe and Japan typically 30–40% higher. Middle East 10–15% lower. All figures in USD millions unless stated.</div>
<div class="footer-tag">AI DC COST MODEL · 2026</div>
</footer>
<!-- Popover -->
<div class="popover-overlay" id="pop-overlay"></div>
<div class="popover" id="popover">
<div class="pop-header">
<div class="pop-dot" id="pop-dot"></div>
<div style="flex:1;">
<div class="pop-title" id="pop-title"></div>
<div class="pop-desc" id="pop-desc"></div>
</div>
<button class="pop-close" id="pop-close">×</button>
</div>
<div class="pop-cost-at" id="pop-cost-at"></div>
<div class="pop-body">
<div class="pop-section">Cost components</div>
<div class="pop-items" id="pop-items"></div>
<div class="pop-refs" id="pop-refs"></div>
</div>
</div>
<script>
const cats = [
{
name: 'AI accelerators (GPU / Blackwell)',
group: 'IT equipment & fit-out',
base: 16.0, exp: 1.00, color: '#4a90d9',
scaleName: 'Linear (1:1)', scaleClass: 'badge-linear',
desc: 'The dominant cost driver. Blackwell-generation GPU accelerators account for ~40% of all-in capex. There is no meaningful bulk discount at data center scale — Nvidia sets the price.',
items: [
{ name: 'GPU accelerators (NVIDIA Blackwell B200 / GB200)', pct: 62, note: '~$30–40K per GPU; ~250–320 GPUs per MW of IT load at 70–100 kW rack densities' },
{ name: 'DGX / HGX server chassis & host CPUs', pct: 13, note: 'AMD EPYC or Intel Xeon host CPUs; chassis, baseboard, PSU — sold as part of the DGX SuperPod system' },
{ name: 'NVLink interconnect & HGX baseboard', pct: 12, note: 'Proprietary high-bandwidth GPU-to-GPU interconnect within each node; not substitutable with commodity hardware' },
{ name: 'Spare GPU inventory (hot-swap buffer)', pct: 9, note: '5–10% spare pool held on-site; GPU failure in a training or inference cluster causes full-rack downtime without spares' },
{ name: 'Acceptance testing & firmware qualification', pct: 4, note: 'Multi-week burn-in, performance validation, and driver/firmware sign-off before production deployment' },
],
refs: [
'Bernstein Research: GB200/NVL72 rack at ~$5.9M (~$3.4M compute + $2.5M infra), Nov 2025',
'NVIDIA FY Q2 2026 earnings: $50–60B per GW campus cost stated on call',
'Investing.com / Bernstein: GPUs = 39% of total AI data center capex, Nov 2025',
'McKinsey: $3.1T of $5.2T total AI DC investment allocated to chip/hardware vendors',
]
},
{
name: 'Host servers & node hardware',
group: 'IT equipment & fit-out',
base: 2.50, exp: 1.00, color: '#5ba0e0',
scaleName: 'Linear (1:1)', scaleClass: 'badge-linear',
desc: 'CPU-based host infrastructure that manages the GPU clusters, runs orchestration, handles ingress/egress, and supports auxiliary workloads. Scales directly with GPU count.',
items: [
{ name: 'Server chassis, motherboards & PSUs', pct: 30, note: 'Standard 2U rackmount servers; density ~20 per rack for management/orchestration nodes' },
{ name: 'Host CPUs (AMD EPYC / Intel Xeon)', pct: 24, note: 'High core-count EPYC or Sapphire Rapids CPUs for parallel workload dispatch and I/O management' },
{ name: 'DRAM — DDR5 system memory', pct: 18, note: '512 GB–2 TB per management node; lower HBM dependency than GPU nodes but still memory-intensive' },
{ name: 'Boot/OS NVMe SSDs', pct: 10, note: 'Fast local NVMe for OS, container images, and model cache; typically 2–4 TB per node' },
{ name: 'Rack hardware, rails & cable management', pct: 10, note: 'Physical rack infrastructure, blanking panels, cable trays, and tooling' },
{ name: 'BMC / server management hardware', pct: 8, note: 'Out-of-band management (iDRAC, iLO) for remote power cycling and diagnostics without OS dependency' },
],
refs: [
'Standard server OEM pricing 2025–2026 (Dell PowerEdge, HPE ProLiant, Supermicro)',
'Alpha Matica: Deconstructing the Data Center cost structure, Jan 2026',
]
},
{
name: 'High-speed networking (InfiniBand)',
group: 'IT equipment & fit-out',
base: 3.50, exp: 0.95, color: '#3b82f6',
scaleName: 'Near-linear', scaleClass: 'badge-near',
desc: 'AI inference at scale requires ultra-low-latency GPU-to-GPU networking. InfiniBand NDR dominates; slight economies emerge from fewer redundant spine switches per rack at large scale.',
items: [
{ name: 'NDR InfiniBand spine & leaf switches (NVIDIA Quantum-3)', pct: 42, note: '$1,200–$1,500 per port at 400 Gb/s; thousands of ports needed per MW; no viable commodity substitute' },
{ name: 'InfiniBand host channel adapters (HCAs) per server', pct: 22, note: '~$2,000–$3,500 per dual-port HCA; one per GPU node required for full fabric connectivity' },
{ name: 'Optical transceivers & DAC cables', pct: 18, note: '400G–800G optical modules at ~$300–$600 each; a 1 MW cluster may require 2,000+ transceivers' },
{ name: 'Top-of-rack Ethernet (management plane)', pct: 10, note: 'Standard 25G/100G Ethernet for out-of-band management, storage access, and internet egress' },
{ name: 'Patch panels, fibre trays & structured cabling', pct: 8, note: 'Pre-terminated MPO fibre trunks; high-density patch panels; cable management for dense GPU racks' },
],
refs: [
'NVIDIA Quantum-3 NDR InfiniBand switch pricing 2025–2026',
'Shield Operations: InfiniBand switches drawing 1,200–1,500W each, thousands needed per cluster, Feb 2026',
'Alpha Matica: networking as significant AI data center sub-cost, Jan 2026',
]
},
{
name: 'Storage arrays & HBM memory',
group: 'IT equipment & fit-out',
base: 0.50, exp: 0.95, color: '#6ea8e8',
scaleName: 'Near-linear', scaleClass: 'badge-near',
desc: 'Shared storage for model weights, training checkpoints, and inference datasets. Smaller at inference vs training workloads; slight economies from larger array configurations.',
items: [
{ name: 'All-NVMe shared storage arrays (model weights)', pct: 48, note: 'High-throughput NVMe arrays for low-latency model weight serving; ~500 TB–2 PB per MW of inference capacity' },
{ name: 'Object/bulk storage (checkpoint & dataset tier)', pct: 30, note: 'Lower-cost high-capacity storage for cold checkpoints and training datasets; often hybrid NVMe + HDD' },
{ name: 'Storage networking (NVMe-oF / RDMA fabric)', pct: 22, note: 'Dedicated storage fabric using NVMe over Fabrics or Fibre Channel; essential for sub-millisecond model load times' },
],
refs: [
'Enterprise NVMe array pricing 2025–2026 (Pure Storage, NetApp, VAST Data)',
'Seagate Mozaic 3+/4 HAMR platform for data center storage, sampled H1 2026',
'IoT Analytics: Data Centre Equipment & Infrastructure Market Report 2025–2030, Nov 2025',
]
},
{
name: 'Liquid cooling (CDUs, plumbing)',
group: 'IT equipment & fit-out',
base: 3.00, exp: 0.85, color: '#3ecf8e',
scaleName: 'Moderate economies', scaleClass: 'badge-moderate',
desc: 'Mandatory for AI inference. At 50–100 kW per rack, air cooling is physically impossible. Liquid cooling adds significant capex but reduces operating costs substantially via better PUE.',
items: [
{ name: 'Coolant Distribution Units (CDUs)', pct: 38, note: 'CDUs are the intelligent hubs connecting facility chilled water to IT cold plates; capacity 300 kW–10 MW each; 12–18 month lead times as of 2026' },
{ name: 'Direct-to-chip cold plates & manifolds', pct: 27, note: 'Individual cold plates per GPU; aluminium or copper; includes quick-disconnect manifolds for hot-swap servicing' },
{ name: 'Facility-side piping & distribution headers', pct: 17, note: 'Insulated stainless-steel or CPVC piping runs from mechanical room to each row; must handle 40°C return temperatures' },
{ name: 'Pumps, heat exchangers & dry coolers', pct: 12, note: 'Redundant pump sets; plate heat exchangers to isolate facility and IT water loops; dry coolers for ambient rejection' },
{ name: 'Leak detection & real-time monitoring', pct: 6, note: 'Sensing cables under raised floor and along pipe runs; integrated with BMS for automated shutoff on detection' },
],
refs: [
'GPUnex Blog: liquid cooling adds $500K–$2M/MW capex; AI racks exceed 50 kW/rack by early 2026, Feb 2026',
'mlq.ai: CDU market growing at 33% CAGR from ~$1B to $7.7B; integrated solutions $2–3M/MW, Dec 2025',
'IoT Analytics: Johnson Controls Silent-Aire CDU platform 500 kW–10 MW, Sep 2025',
'Shield Operations: liquid cooling achieves PUE 1.10–1.15 vs air-cooled 1.4–1.6, Feb 2026',
]
},
{
name: 'In-room power distribution (PDUs)',
group: 'IT equipment & fit-out',
base: 1.50, exp: 0.90, color: '#10b981',
scaleName: 'Moderate economies', scaleClass: 'badge-moderate',
desc: 'Power distribution at rack level. AI racks require intelligent PDUs rated for 30–60A circuits at 208–415V — substantially more expensive than standard enterprise PDUs.',
items: [
{ name: 'Intelligent rack PDUs (metered & switched)', pct: 32, note: '$2,000–$8,000 per PDU; 2 per rack standard for redundancy; per-outlet monitoring for capacity planning' },
{ name: 'Overhead busway / raised-floor busbar system', pct: 28, note: 'Plug-in busway runs replace individual cable runs; critical for dense GPU rows requiring frequent reconfigurations' },
{ name: 'Branch circuit monitoring panels', pct: 20, note: 'Per-circuit current monitoring upstream of PDUs; integrates with DCIM for real-time capacity management' },
{ name: 'Cabinet & rack hardware', pct: 20, note: '42–52U open-frame or enclosed racks; must be rated for 1,500–3,000 kg point load for dense GPU nodes' },
],
refs: [
'Vertiv, Schneider Electric, and Raritan intelligent PDU pricing 2025–2026',
'IoT Analytics: AI-ready electrical architectures; AI racks exceeding 100 kW/rack requiring full distribution redesign, Nov 2025',
]
},
{
name: 'Electrical (switchgear, UPS, generators)',
group: 'Building & infrastructure',
base: 5.50, exp: 0.70, color: '#f5a623',
scaleName: 'Strong economies', scaleClass: 'badge-strong',
desc: 'The largest infrastructure sub-cost and where the strongest economies appear. One large substation and transformer installation serves 10× more capacity than ten small ones, at far less than 10× the price.',
items: [
{ name: 'Medium-voltage switchgear & transformers', pct: 36, note: 'Custom MV/LV transformers (33kV→480V); lead times now 12–18 months for large units; biggest capex with strongest economies' },
{ name: 'UPS systems (2N redundancy, online double-conversion)', pct: 27, note: 'Schneider Galaxy VXL or ABB MegaFlex class; 500 kW–1,250 kW per module; 2N means full duplicate system' },
{ name: 'Backup diesel generators (N+1)', pct: 18, note: '1–3 MW diesel gensets; N+1 minimum; 48–96 hour fuel storage on-site; auto-start within 10 seconds of utility loss' },
{ name: 'Automatic Transfer Switches (ATS)', pct: 10, note: 'Static or mechanical ATS between utility, UPS, and generator feeds; must transfer in <100 ms for continuous GPU operation' },
{ name: 'Power monitoring, metering & SCADA', pct: 5, note: 'Real-time power quality monitoring; PUE calculation; utility billing reconciliation; demand-response programme integration' },
{ name: 'Electrical installation labour', pct: 4, note: 'Licensed electricians; strongly regulated; specialist shortage driving labour cost inflation in 2025–2026' },
],
refs: [
'JLL Global Data Center Outlook 2026: electrical infrastructure dominant building-side cost; shell & core $11.3M/MW average',
'IoT Analytics: Schneider Electric Galaxy VXL UPS (Apr 2025); ABB MegaFlex AI-ready (Jul 2025)',
'ConstructElements: power infrastructure "limiting factor rather than building size" in most 2026 markets, Feb 2026',
'GPUnex: power availability replaced chip supply as #1 AI infrastructure constraint by 2026, Feb 2026',
]
},
{
name: 'Civil & structural (shell, core)',
group: 'Building & infrastructure',
base: 3.00, exp: 0.75, color: '#f59e0b',
scaleName: 'Strong economies', scaleClass: 'badge-strong',
desc: 'Building construction has genuine volume economies. Fixed design, permitting, and mobilisation costs are amortised over more floor space. Larger builds also attract better contractor pricing.',
items: [
{ name: 'Structural steel frame & connections', pct: 33, note: 'Long-span steel frames; must support 1,500–3,000 kg/m² point loads for dense GPU rack rows and overhead cooling infrastructure' },
{ name: 'Concrete foundations & ground slab', pct: 27, note: 'Piled foundations where needed; reinforced slab rated for heavy equipment; specialist vibration isolation for sensitive workloads' },
{ name: 'Roofing, cladding & weatherproofing envelope', pct: 18, note: 'Insulated metal cladding; EPDM or TPO roofing; designed for 50-year operational life with minimal maintenance' },
{ name: 'Site preparation & earthworks', pct: 12, note: 'Grading, excavation, compaction; varies enormously by terrain; brownfield sites typically cheaper than greenfield' },
{ name: 'External civil works (roads, drainage, fencing)', pct: 10, note: 'Heavy vehicle access routes; stormwater management; perimeter fencing and gatehouse infrastructure' },
],
refs: [
'Turner & Townsend Data Centre Construction Cost Index 2025–2026: average $10.7M/MW shell & core (2025); ~$11.3M forecast 2026',
'ConstructConnect: average cost per sq ft reached $1,033 in 2025, up from $535 in 2023',
'ConstructElements: $10–12M/MW typical shell-and-core range for standard hyperscale, Feb 2026',
]
},
{
name: 'Mechanical / base HVAC',
group: 'Building & infrastructure',
base: 2.00, exp: 0.75, color: '#fbbf24',
scaleName: 'Strong economies', scaleClass: 'badge-strong',
desc: 'Base building HVAC handles office areas, battery rooms, electrical switchrooms, and supplemental cooling. Liquid cooling handles the GPU heat load; HVAC handles everything else.',
items: [
{ name: 'Chillers & cooling towers (supplemental)', pct: 35, note: 'Even with liquid cooling, chillers serve battery rooms, UPS rooms, and offices; larger plants are more efficient per ton' },
{ name: 'Computer Room Air Handlers (CRAHs)', pct: 30, note: 'Supplemental in-row or overhead CRAHs for hot-spot management and air-side economisation in cooler climates' },
{ name: 'General building HVAC (offices, NOC, comms)', pct: 20, note: 'Standard commercial HVAC for occupied spaces; a relatively small fraction of total mechanical spend in AI facilities' },
{ name: 'Mechanical plumbing & installation labour', pct: 15, note: 'Pipe fitting, insulation, valve installation; includes commissioning and pressure testing of all mechanical systems' },
],
refs: [
'mlq.ai: air-cooled facilities achieve PUE 1.4–1.6; well-designed liquid cooling achieves 1.10–1.20, Dec 2025',
'Shield Operations: liquid cooling mandatory at 50+ kW/rack; HVAC handles residual facility load, Feb 2026',
]
},
{
name: 'Land, permits & project management',
group: 'Building & infrastructure',
base: 1.50, exp: 0.50, color: '#d97706',
scaleName: 'Very strong economies', scaleClass: 'badge-vstrong',
desc: 'Near-fixed costs that barely move with scale. You buy one plot, run one permitting process, and hire one PM team — whether the building is 10 MW or 200 MW. The highest-economy line item.',
items: [
{ name: 'Land acquisition', pct: 33, note: 'Highly variable: $1M/acre in rural Texas vs $10M+/acre in Northern Virginia or Dublin. Power proximity typically trumps land cost.' },
{ name: 'Planning & environmental permits', pct: 20, note: 'Environmental impact assessments, grid connection applications, building warrants; one process regardless of site size' },
{ name: 'Construction project management', pct: 27, note: 'PM and QS fees typically 3–5% of construction cost; the percentage actually decreases at larger project sizes' },
{ name: 'Legal, professional & advisory fees', pct: 13, note: 'Site acquisition legal costs, planning solicitors, structural and M&E consultant fees at concept and design stages' },
{ name: 'Security perimeter (initial fencing & gatehouse)', pct: 7, note: 'Site hoarding during construction; permanent perimeter fencing and gatehouse spec\'d at design stage' },
],
refs: [
'JLL 2026 Global Data Center Outlook: "speed to power is the primary criteria driving site selection, followed by community support, latency and proximity to customers"',
'ConstructElements: land selection impacts cost significantly via off-site power, road access, and grading requirements, Feb 2026',
'GPUnex: Northern Virginia connection wait times exceed 3–5 years for new large-scale deployments, Feb 2026',
]
},
{
name: 'Fire suppression, security & misc.',
group: 'Building & infrastructure',
base: 1.00, exp: 0.50, color: '#b45309',
scaleName: 'Very strong economies', scaleClass: 'badge-vstrong',
desc: 'Largely fixed overhead. A 100 MW facility does not need 100× the security staff of a 1 MW facility. Clean-agent fire suppression scales by zone count, not linearly by power capacity.',
items: [
{ name: 'Clean-agent fire suppression (FM-200 / Novec 1230)', pct: 30, note: 'Gaseous suppression in whitespace and electrical rooms; zoned by area not by MW; one zone protects many racks' },
{ name: 'CCTV surveillance system', pct: 20, note: 'Pan-tilt-zoom cameras, NVR infrastructure, 90-day retention; camera count grows slowly with facility area' },
{ name: 'Access control & biometric systems', pct: 20, note: 'Mantraps, biometric readers, card access throughout; Tier 3 mandates multi-factor physical access at whitespace entry' },
{ name: 'Building Management System (BMS)', pct: 15, note: 'Integrated DCIM and BMS platform; one system manages the whole facility; major fixed-cost component' },
{ name: 'Signage, misc. fit-out & commissioning snagging', pct: 15, note: 'Flooring, painting, signage, wayfinding, snagging lists; relatively fixed costs per building regardless of size' },
],
refs: [
'Uptime Institute Tier Standards: Tier 3 mandates N+1 fire suppression zoning and multi-factor physical access control',
'Alpha Matica: Deconstructing the Data Center — fire, security and misc as infrastructure overhead, Jan 2026',
]
},
];
const scaleBadgeStyle = {
'badge-linear': 'background:#3d1515; color:#f09595;',
'badge-near': 'background:#3d2a0a; color:#EF9F27;',
'badge-moderate': 'background:#162909; color:#97C459;',
'badge-strong': 'background:#04201a; color:#5DCAA5;',
'badge-vstrong': 'background:#051b30; color:#85B7EB;',
};
function fmt(v) {
if (v >= 1000) return '$' + (Math.round(v / 10) / 100).toFixed(2) + 'B';
if (v >= 100) return '$' + Math.round(v) + 'M';
if (v >= 10) return '$' + (Math.round(v * 10) / 10).toFixed(1) + 'M';
if (v >= 1) return '$' + (Math.round(v * 100) / 100).toFixed(2) + 'M';
return '$' + (Math.round(v * 1000) / 1000).toFixed(3) + 'M';
}
function totalAt(mw) {
return cats.reduce((s, c) => s + c.base * Math.pow(mw, c.exp), 0);
}
let currentMW = 1;
let activeRow = null;
function render(mw) {
currentMW = mw;
document.getElementById('mw-display').textContent = mw;
const total = totalAt(mw);
const perMW = total / mw;
const linearTotal = cats.reduce((s, c) => s + c.base * mw, 0);
const saved = linearTotal - total;
const savedPct = mw > 1 ? Math.round(saved / linearTotal * 100) : 0;
document.getElementById('total-cost').textContent = fmt(total);
document.getElementById('total-sub').textContent = 'at ' + mw + ' MW';
document.getElementById('per-mw').textContent = fmt(perMW);
document.getElementById('per-mw-sub').textContent = mw > 1
? (Math.round((perMW / 40 - 1) * 100) + '% vs 1 MW baseline')
: '1 MW baseline';
document.getElementById('saving-val').textContent = mw > 1 ? fmt(saved) : '—';
document.getElementById('saving-sub').textContent = mw > 1
? (savedPct + '% cheaper than if all costs scaled linearly')
: 'economies of scale';
let html = '';
let lastGroup = '';
cats.forEach((c, i) => {
if (c.group !== lastGroup) {
html += `<tr class="group-row"><td colspan="6">${c.group}</td></tr>`;
lastGroup = c.group;
}
const totalC = c.base * Math.pow(mw, c.exp);
const perMWc = totalC / mw;
const savingPct = mw > 1 ? Math.round((c.base - perMWc) / c.base * 100) : 0;
html += `<tr class="data-row" data-idx="${i}">
<td>
<div class="cat-name">
<div class="cat-dot" style="background:${c.color}"></div>
${c.name}
<span class="hint-icon" title="Click for detail breakdown">i</span>
</div>
</td>
<td class="mono">$${c.base}M</td>
<td class="mono">${fmt(totalC)}</td>
<td class="mono">${fmt(perMWc)}</td>
<td>${savingPct > 1 ? `<span class="saving-val">−${savingPct}%</span>` : `<span class="saving-none">—</span>`}</td>
<td><span class="scale-badge" style="${scaleBadgeStyle[c.scaleClass]}">${c.scaleName}</span></td>
</tr>`;
});
const blendedPerMW = total / mw;
const totalLinear = cats.reduce((s, c) => s + c.base * mw, 0);
const overallSaving = mw > 1 ? Math.round((40 - blendedPerMW) / 40 * 100) : 0;
html += `<tr class="total-row">
<td>Total (all categories)</td>
<td class="mono">$40.0M</td>
<td class="mono">${fmt(total)}</td>
<td class="mono">${fmt(blendedPerMW)}</td>
<td>${overallSaving > 0 ? `<span class="saving-val">−${overallSaving}%</span>` : `<span class="saving-none">—</span>`}</td>
<td></td>
</tr>`;
document.getElementById('table-body').innerHTML = html;
document.querySelectorAll('tr.data-row').forEach(row => {
row.addEventListener('click', function(e) {
const idx = parseInt(this.dataset.idx);
showPopover(idx, this);
});
});
}
function showPopover(idx, rowEl) {
const c = cats[idx];
const mw = currentMW;
const totalC = c.base * Math.pow(mw, c.exp);
const perMWc = totalC / mw;
document.getElementById('pop-dot').style.background = c.color;
document.getElementById('pop-title').textContent = c.name;
document.getElementById('pop-desc').textContent = c.desc;
document.getElementById('pop-cost-at').textContent =
`At ${mw} MW: ${fmt(totalC)} total · ${fmt(perMWc)}/MW`;
let itemsHtml = '';
c.items.forEach(item => {
const itemCost = totalC * item.pct / 100;
itemsHtml += `<div class="pop-item">
<div class="pop-item-left">
<div class="pop-item-name">${item.name}</div>
<div class="pop-item-note">${item.note}</div>
<div class="pop-bar-wrap"><div class="pop-bar" style="width:${item.pct}%; background:${c.color}; opacity:0.6;"></div></div>
</div>
<div class="pop-item-right">
<div class="pop-item-cost">${fmt(itemCost)}</div>
<div class="pop-item-pct">${item.pct}%</div>
</div>
</div>`;
});
document.getElementById('pop-items').innerHTML = itemsHtml;
let refsHtml = `<div class="pop-ref-title">Sources</div>`;
c.refs.forEach(r => { refsHtml += `<div class="pop-ref-item">${r}</div>`; });
document.getElementById('pop-refs').innerHTML = refsHtml;
const pop = document.getElementById('popover');
pop.style.display = 'block';
document.getElementById('pop-overlay').style.display = 'block';
const rect = rowEl.getBoundingClientRect();
const scrollY = window.scrollY;
const popH = 560;
const popW = 420;
let top = rect.bottom + scrollY + 4;
let left = rect.left + 200;
if (left + popW > window.innerWidth - 16) left = window.innerWidth - popW - 16;
if (left < 8) left = 8;
if (top + popH > scrollY + window.innerHeight - 8) top = rect.top + scrollY - popH - 4;
if (top < scrollY + 8) top = scrollY + 8;
pop.style.top = top + 'px';
pop.style.left = left + 'px';
pop.classList.add('visible');
document.getElementById('pop-overlay').classList.add('visible');
}
function closePopover() {
document.getElementById('popover').classList.remove('visible');
document.getElementById('pop-overlay').classList.remove('visible');
document.getElementById('popover').style.display = 'none';
document.getElementById('pop-overlay').style.display = 'none';
}
document.getElementById('pop-close').addEventListener('click', closePopover);
document.getElementById('pop-overlay').addEventListener('click', closePopover);
document.getElementById('mw-slider').addEventListener('input', e => {
render(+e.target.value);
closePopover();
});
// Chart
const labels = [], data = [];
for (let mw = 1; mw <= 200; mw++) {
labels.push(mw);
data.push(Math.round(totalAt(mw) / mw * 10) / 10);
}
new Chart(document.getElementById('curve-chart'), {
type: 'line',
data: {
labels,
datasets: [{
label: 'Cost/MW ($M)',
data,
borderColor: '#f5a623',
backgroundColor: 'rgba(245,166,35,0.07)',
fill: true,
tension: 0.4,
pointRadius: 0,
borderWidth: 2.5,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: '#1a1f2e',
borderColor: 'rgba(255,255,255,0.1)',
borderWidth: 1,
titleColor: '#8b90a0',
bodyColor: '#f5a623',
titleFont: { family: 'IBM Plex Mono', size: 11 },
bodyFont: { family: 'IBM Plex Mono', size: 13 },
callbacks: {
title: ctx => ctx[0].label + ' MW',
label: ctx => 'Cost/MW: $' + ctx.raw.toFixed(1) + 'M',
}
}
},
scales: {
x: {
ticks: {
color: '#555b70',
maxTicksLimit: 10,
font: { family: 'IBM Plex Mono', size: 11 },
callback: v => v + ' MW'
},
grid: { color: 'rgba(255,255,255,0.04)' }
},
y: {
ticks: {
color: '#555b70',
font: { family: 'IBM Plex Mono', size: 11 },
callback: v => '$' + Math.round(v) + 'M'
},
grid: { color: 'rgba(255,255,255,0.04)' }
}
}
}
});
render(1);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment