Provider X is the pick for a three-year non-production workload. On-demand it totals $529.6k at 10% yearly utilisation growth, against $546.2k for Y and $579.2k for Z, and X stays cheapest at every growth rate from 0% to 30% when all three cost lines grow together. Reserved compute (a one-year commitment priced 30% below on-demand, where on-demand means paying the full list rate by the hour with no commitment) cuts X to $410.4k, but only pay for it if the compute actually runs most of the year, which non-production rarely does.
python
providers = { # year-1 list cost in $k per year
"X": {"compute": 120, "storage": 30, "egress": 10},
"Y": {"compute": 95, "storage": 45, "egress": 25},
"Z": {"compute": 110, "storage": 25, "egress": 40},
}
def tco(p, growth, reserved):
total = 0.0
for year in range(3):
scale = (1 + growth) ** year # utilisation index: 1.00, 1.10, 1.21
compute = p["compute"] * scale * (0.70 if reserved else 1.0)
total += compute + p["storage"] * scale + p["egress"] * scale
return total
for reserved in (False, True):
label = "1-yr reserved compute" if reserved else "on-demand compute"
print(label)
for g in (0.0, 0.10, 0.20, 0.30):
row = {n: round(tco(p, g, reserved), 1) for n, p in providers.items()}
best = min(row, key=row.get)
print(f" growth {g:>4.0%}: " + " ".join(f"{n}={v:>6.1f}" for n, v in row.items()) + f" -> best {best}")
# Stress test 1: only compute usage grows; storage and egress stay flat.
def tco_compute_only(p, growth, reserved):
total = 0.0
for year in range(3):
compute = p["compute"] * (1 + growth) ** year * (0.70 if reserved else 1.0)
total += compute + p["storage"] + p["egress"]
return total
print("compute-only growth, on-demand")
for g in (0.10, 0.20, 0.30):
row = {n: round(tco_compute_only(p, g, False), 1) for n, p in providers.items()}
print(f" growth {g:.0%}: " + " ".join(f"{n}={v:.1f}" for n, v in row.items()) + f" -> best {min(row, key=row.get)}")
# Smallest growth rate (0.1% steps) at which Y beats X on compute-only growth.
for label, reserved in (("on-demand", False), ("reserved", True)):
flip = next((g / 1000 for g in range(0, 1000)
if tco_compute_only(providers["Y"], g / 1000, reserved)
< tco_compute_only(providers["X"], g / 1000, reserved)), None)
print(f"Y beats X on compute-only growth ({label}) from growth of about {flip:.1%}" if flip else f"no flip ({label})")
# Stress test 2: egress volume multiplier at 10% growth, on-demand.
print("egress multiplier at 10% growth, on-demand")
for k in (1, 2, 4):
row = {}
for n, p in providers.items():
q = dict(p, egress=p["egress"] * k)
row[n] = round(tco(q, 0.10, False), 1)
print(f" egress x{k}: " + " ".join(f"{n}={v:.1f}" for n, v in row.items()))
# Reserved pays off only if the instance runs more than 70% of hours.
print("reserved vs on-demand, X compute, year-1 $k at utilisation of hours")
for u in (0.30, 0.50, 0.70, 1.00):
on_demand = 120 * u
reserved = 120 * 0.70
print(f" {u:.0%} of hours: on-demand {on_demand:.1f} reserved {reserved:.1f}")
text
on-demand compute
growth 0%: X= 480.0 Y= 495.0 Z= 525.0 -> best X
growth 10%: X= 529.6 Y= 546.2 Z= 579.2 -> best X
growth 20%: X= 582.4 Y= 600.6 Z= 637.0 -> best X
growth 30%: X= 638.4 Y= 658.4 Z= 698.2 -> best X
1-yr reserved compute
growth 0%: X= 372.0 Y= 409.5 Z= 426.0 -> best X
growth 10%: X= 410.4 Y= 451.8 Z= 470.0 -> best X
growth 20%: X= 451.4 Y= 496.9 Z= 516.9 -> best X
growth 30%: X= 494.8 Y= 544.6 Z= 566.6 -> best X
compute-only growth, on-demand
growth 10%: X=517.2 Y=524.5 Z=559.1 -> best X
growth 20%: X=556.8 Y=555.8 Z=595.4 -> best Y
growth 30%: X=598.8 Y=589.0 Z=633.9 -> best Y
Y beats X on compute-only growth (on-demand) from growth of about 18.9%
Y beats X on compute-only growth (reserved) from growth of about 59.6%
egress multiplier at 10% growth, on-demand
egress x1: X=529.6 Y=546.2 Z=579.2
egress x2: X=562.7 Y=628.9 Z=711.7
egress x4: X=628.9 Y=794.4 Z=976.5
reserved vs on-demand, X compute, year-1 $k at utilisation of hours
30% of hours: on-demand 36.0 reserved 84.0
50% of hours: on-demand 60.0 reserved 84.0
70% of hours: on-demand 84.0 reserved 84.0
100% of hours: on-demand 120.0 reserved 84.0