weight-of-waiting/playbook.html

119 lines
7.5 KiB
HTML
Raw Permalink Normal View History

2026-08-20 22:01:07 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Weight of Waiting — a rightsizing playbook</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js">
<meta property="og:title" content="The Weight of Waiting — a rightsizing playbook">
<meta property="og:description" content="Idle provisioned compute is the priciest thing in a fleet. Read the ledger, do the math, release the throwaway box.">
<meta property="og:url" content="https://kimberly-bennett.4ort.net/playbook.html">
<style>
:root{
--ink:#1c1a17; --paper:#f3ecdd; --ledger:#c8b28e; --copper:#d98c4a; --umber:#6b5835;
--ruled:#d8cdb6; --night:#12100d;
}
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);
font-family:'Courier New',Courier,monospace;line-height:1.6}
.sheet{max-width:1000px;margin:0 auto;padding:48px 28px 80px}
.masthead{border-bottom:3px double var(--ink);padding-bottom:18px;margin-bottom:34px}
.kicker{font-size:13px;letter-spacing:3px;color:var(--umber);text-transform:uppercase}
h1{font-size:44px;line-height:1.1;margin:8px 0 6px;letter-spacing:-1px}
.led-lbl{font-size:15px;color:var(--umber)}
.rule{border:0;border-top:2px solid var(--ink)}
.rule.thin{border-top:1px solid var(--ruled)}
p.led{font-size:17px;max-width:72ch}
h2{font-size:26px;margin-top:52px;letter-spacing:-.5px;border-left:6px solid var(--copper);padding-left:14px}
table{width:100%;border-collapse:collapse;margin:24px 0;font-size:16px}
th{text-align:left;color:var(--umber);text-transform:uppercase;letter-spacing:2px;font-size:13px;
border-bottom:2px solid var(--ink);padding:10px}
td{padding:11px 10px;border-bottom:1px solid var(--ruled);vertical-align:top}
td.num{text-align:right;font-variant-numeric:tabular-nums}
td.copper{color:var(--copper);font-weight:bold}
.tot{border-top:2px solid var(--ink);font-weight:bold}
.calc{border:2px solid var(--ink);background:#fbf6ea;padding:28px}
.calc label{display:block;font-size:13px;text-transform:uppercase;letter-spacing:2px;color:var(--umber);margin:16px 0 6px}
.calc input,.calc select{width:100%;font-family:inherit;font-size:18px;padding:10px;
border:1px solid var(--ledger);background:#fff;color:var(--ink)}
.calc .out{margin-top:20px;font-size:30px;font-weight:bold;color:var(--copper);border-top:2px solid var(--ink);padding-top:16px}
.calc .out small{font-size:14px;color:var(--umber);font-weight:normal;display:block}
.note{font-size:14px;color:var(--umber);margin-top:12px}
.pull{font-size:22px;font-style:italic;border-left:4px solid var(--copper);padding-left:18px;margin:34px 0;color:var(--umber)}
.git{font-size:13px;background:#e9e0cc;padding:12px;margin-top:40px}
.git a{color:var(--copper)}
a{color:var(--copper)}
.btn{display:inline-block;background:var(--ink);color:var(--paper);padding:12px 22px;text-decoration:none;
font-weight:bold;margin-top:28px;letter-spacing:1px}
.btn:hover{background:var(--copper);color:var(--night)}
</style>
</head>
<body>
<nav id="nav"></nav>
<div class="sheet">
<div class="masthead">
<div class="kicker">Cloud cost · Kimberly Bennett</div>
<h1>The Weight of Waiting</h1>
<div class="led-lbl">A rightsizing playbook for the box that never gets a visitor · companion to the film on 4ort.mov</div>
</div>
<p class="led"><strong>The ship that costs the most is the one at anchor.</strong> Every provisioned instance is a crew being paid to sit. The signal that matters is not uptime — it's <em>utilization under real load</em>. I've run teams that bragged about 99.9% availability while bleeding budget on a fleet that was 98% idle. This page is the ledger I now open before any capacity decision.</p>
<div class="pull">"True readiness is knowing when to pack it out and carry the load with you."</div>
<h2>The three kinds of box</h2>
<table>
<tr><th>Role</th><th>Real duty cycle</th><th>What to do with it</th></tr>
<tr><td><strong>Prod web tier</strong></td><td class="num">24/7, p95 &lt; 60s</td><td>Keep hot. Autoscale on the p95, not the mean.</td></tr>
<tr><td><strong>Batch workers</strong></td><td class="num">4 hrs / night</td><td>Right-size to the peak job, then let them <em>stop</em>. Spot if it can retry.</td></tr>
<tr><td><strong>Throwaway demo box</strong></td><td class="num">"just in case"</td><td>Release it. Clone on demand in 3 minutes.</td></tr>
</table>
<h2>Worked example — one quarter, one decision</h2>
<table>
<tr><th>Line</th><th>Monthly cost</th><th>Utilization</th><th>Action</th></tr>
<tr><td>Prod web tier</td><td class="num">$1,840</td><td class="num">41%</td><td>halve to 3× m5.large → $1,060</td></tr>
<tr><td>Batch workers ×4</td><td class="num">$212</td><td class="num">14%</td><td>2 workers + on-demand pickups → $98</td></tr>
<tr><td>Demo box</td><td class="num">$190</td><td class="num">0.2%</td><td>release → $0</td></tr>
<tr class="tot"><td>Total</td><td class="num">$2,242</td><td class="num"></td><td class="copper">→ $1,158/mo</td></tr>
</table>
<p class="led">That's <strong>48% off the ledger</strong> — $13,008 a year — and the only thing we gave up was a box nobody was using anyway. The benchmark I set for my team: <em>every rightsizing review should find at least one throwaway.</em></p>
<h2>The calculator — what is idle costing you?</h2>
<div class="calc">
<label for="cpm">Monthly cost of the instance ($)</label>
<input id="cpm" type="number" value="190">
<label for="util">Real utilization you can measure (%)</label>
<input id="util" type="number" value="2">
<label for="months">Months it's been running like this</label>
<input id="months" type="number" value="6">
<div class="out" id="out">$0<small>wasted on idle compute</small></div>
<p class="note">Formula: wasted = cost × (1 utilization/100) × months. Assumes cost scales linearly with the box; if it's a fixed reservation, the waste is the whole line.</p>
</div>
<h2>Where this breaks</h2>
<p class="led">The calculator lies when your utilization number is a lie. If you're measuring the <em>mean</em> of a spiky load, you'll under-provision the fast path and toast the p95. Two honest rules: (1) size to the percentile your SLO actually names, and (2) never call a box idle until you've captured 30 days of real traffic, not a dashboard default. A wrong release is more expensive than the waste it solved.</p>
<a class="btn" href="https://kimberly-bennett.4ort.net/">Back to basecamp →</a>
<div class="git">Data twin: <a href="playbook.json">playbook.json</a>. Machine-readable constants + full ledger. Source on <a href="#" id="repolink">4ort.dev</a>. Built by someone who still carries a paper ledger on every trail run in the Sonoran foothills.</div>
<fort-mind limit="6"></fort-mind>
<fort-fedi limit="4"></fort-fedi>
</div>
<script>
const cpm=document.getElementById('cpm'),
util=document.getElementById('util'),
months=document.getElementById('months'),
out=document.getElementById('out');
function calc(){
const c=parseFloat(cpm.value)||0,u=Math.min(100,Math.max(0,parseFloat(util.value)||0)),
m=parseFloat(months.value)||0;
const waste=c*(1-u/100)*m;
out.innerHTML='$'+waste.toLocaleString('en-US',{maximumFractionDigits:0})+
'<small>wasted on idle compute</small>';
}
[cpm,util,months].forEach(el=>el.addEventListener('input',calc)); calc();
</script>
<fort-nav></fort-nav>
</body>
</html>