Suppose someone tells you an AI data center is “100 MW.”
You might make a quick calculation:
100 MW × 8,760 hours × $70/MWh = $61.3 million per year
That looks reasonable.
But the example in this article produces about $67.8 million.
Which number is wrong?
Neither number is automatically wrong. The answer depends on what “100 MW” means and which assumptions sit around it.
Is 100 MW the maximum IT capacity?
How heavily is that IT equipment used on average?
How much electricity does cooling and power infrastructure add?
What tariff is actually paid?
And what happens if cheap electricity arrives years later than expensive electricity?
This article turns those questions into a small Python model.
The purpose of the model is not to predict one project perfectly. It is to make the assumptions visible enough to change them.
This is the calculation companion to Why Power, Not Chips, May Limit the AI Data Center Boom.
The Reader Questions Behind the Calculator
Public discussions around data-center power keep circling back to a few practical questions.
What does a 100 MW number actually describe?
Can PUE values be compared directly across facilities?
Do large data centers simply pay a flat electricity price, or do demand charges, minimum commitments and other tariff terms matter?
And when one site is cheaper but slower to energize, how do we make the trade-off visible?
The calculator will not answer every project-finance question.
It will give us a transparent first model.
The Contexta Power-Cost Chain
The core calculation follows one chain:
IT Capacity → Average IT Load → Facility Load → Annual Energy → Electricity Cost
In symbols:
IT MW × Load Factor × PUE × Hours × $/MWh
Each term answers a different question.
| Input | Question it answers | Example |
|---|---|---|
| IT capacity | What is the maximum power assigned to IT equipment? | 100 MW |
| Load factor | What fraction of maximum IT capacity is used on average? | 0.85 |
| PUE | How much facility energy surrounds the IT load? | 1.30 |
| Electricity price | What simplified energy price are we applying? | $70/MWh |
| Hours | How do we convert average power into annual energy? | 8,760 h |
The U.S. Department of Energy defines PUE as total facility energy divided by IT-equipment energy. It also cautions that PUE measures infrastructure energy efficiency, not the overall productivity or value of a data center.[1]
Step 1: Make the Assumptions Visible
HOURS_PER_YEAR = 8_760
it_capacity_mw = 100
average_load_factor = 0.85
pue = 1.30
electricity_price_per_mwh = 70
The important line is not the Python syntax.
It is that every assumption is exposed.
A value of average_load_factor = 0.85 does not mean every GPU is busy exactly 85% of every hour. It is a screening assumption for average IT electrical load.
The IEA’s Energy and AI data product itself separates installed capacity, PUE, load factor and electricity consumption, which is a useful reminder that these are distinct quantities rather than one interchangeable number.[2]
Step 2: Move from 100 MW to Average Facility Load
average_it_load_mw = (
it_capacity_mw
* average_load_factor
)
average_facility_load_mw = (
average_it_load_mw
* pue
)
For the example:
100 MW × 0.85 = 85 MW average IT load
Then:
85 MW × 1.30 = 110.5 MW average facility load
This is the first reason the label “100 MW” can mislead.
If 100 MW means maximum IT capacity, the whole building can average more than 100 MW after facility overhead is included.
Step 3: Turn Power into Annual Energy and Cost
annual_energy_mwh = (
average_facility_load_mw
* HOURS_PER_YEAR
)
annual_electricity_cost = (
annual_energy_mwh
* electricity_price_per_mwh
)
The result is:
Average IT load: 85.0 MW
Average facility load: 110.5 MW
Annual electricity use: 967,980 MWh
Annual electricity cost: $67,758,600
Now the opening puzzle makes sense.
The naive $61.3 million calculation assumed 100 MW of facility load running continuously.
The $67.8 million result assumes 100 MW of maximum IT capacity, an 85% average IT load factor, and a PUE of 1.30.
The model did not discover a hidden law of nature.
It simply made the assumptions explicit.
The Contexta Assumption Ledger
A useful model should tell the reader which numbers are physical definitions, which are measured values, and which are scenarios.
| Input | Type | How to treat it |
|---|---|---|
| 8,760 h/year | Calendar conversion | Fixed for an ordinary year |
| 100 MW IT capacity | Case definition | Replace with the project’s actual definition |
| 0.85 load factor | Scenario / measured operating input | Test several utilization assumptions |
| 1.30 PUE | Design / operating assumption | Use expected or measured annual PUE |
| $70/MWh | Simplified tariff input | Replace with a project-specific tariff or contract model |
| $2M/month delay cost | Scenario input | Never present as a market average |
A model becomes more trustworthy when it makes uncertain numbers easier to replace.
Step 4: Put One Site into a Data Class
from dataclasses import dataclass
@dataclass(frozen=True)
class DataCenterCase:
name: str
it_capacity_mw: float
average_load_factor: float
pue: float
electricity_price_per_mwh: float
grid_connection_delay_months: float = 0.0
monthly_delay_cost: float = 0.0
Using frozen=True makes each case immutable after creation.
If you want another assumption set, create another case instead of silently changing the first one.
That makes comparisons easier to audit.
Step 5: Turn the Equations into a Reusable Function
def calculate_case(case: DataCenterCase) -> dict:
average_it_load_mw = (
case.it_capacity_mw
* case.average_load_factor
)
average_facility_load_mw = (
average_it_load_mw
* case.pue
)
annual_energy_mwh = (
average_facility_load_mw
* HOURS_PER_YEAR
)
annual_electricity_cost = (
annual_energy_mwh
* case.electricity_price_per_mwh
)
delay_cost = (
case.grid_connection_delay_months
* case.monthly_delay_cost
)
return {
"average_it_load_mw": average_it_load_mw,
"average_facility_load_mw": average_facility_load_mw,
"annual_energy_mwh": annual_energy_mwh,
"annual_electricity_cost": annual_electricity_cost,
"delay_cost": delay_cost,
}
Step 6: Change PUE and Watch the Bill Move
One result is not enough.
Change PUE while holding the other assumptions constant.
import matplotlib.pyplot as plt
import numpy as np
pue_values = np.arange(1.10, 1.61, 0.05)
annual_costs_million = []
for changed_pue in pue_values:
annual_cost = (
it_capacity_mw
* average_load_factor
* changed_pue
* HOURS_PER_YEAR
* electricity_price_per_mwh
)
annual_costs_million.append(
annual_cost / 1_000_000
)
Under this example, every 0.10 increase in PUE adds about $5.21 million to annual electricity cost.
This does not prove that the lowest PUE is always the best project.
A lower PUE can require additional capital, water systems, controls or maintenance.
The graph isolates one side of the trade-off: annual electricity expense.
Why the Electricity Price Is Only a Simplified Input
A reader may reasonably ask: “Do large data centers really pay one flat $/MWh number?”
Often, the full answer is more complicated.
Berkeley Lab’s 2026 review of large-load rate design describes utility approaches that can include minimum bills, contract terms, demand-related obligations, collateral, exit provisions and other mechanisms intended to allocate system costs and financial risk.[3]
So $70/MWh in this calculator is not a universal tariff model.
It is a first screening variable.
A project model can later replace it with:
- energy charges
- demand charges
- time-of-use pricing
- minimum consumption or demand commitments
- grid-upgrade charges
- taxes and fees
- contract-specific escalation
Step 7: Compare Cheap Power with Fast Power
Now create two cases.
site_a = DataCenterCase(
name="Site A: cheap, slow",
it_capacity_mw=100,
average_load_factor=0.85,
pue=1.30,
electricity_price_per_mwh=50,
grid_connection_delay_months=48,
monthly_delay_cost=2_000_000,
)
site_b = DataCenterCase(
name="Site B: costly, fast",
it_capacity_mw=100,
average_load_factor=0.85,
pue=1.30,
electricity_price_per_mwh=75,
grid_connection_delay_months=18,
monthly_delay_cost=2_000_000,
)
Site A annual electricity cost is about $48.4 million.
Site B annual electricity cost is about $72.6 million.
Site A saves about $24.2 million per operating year on this simplified power-price assumption.
But Site A waits 30 months longer.
That lets us ask a better question:
How expensive must one month of delay become before faster power offsets the annual electricity-price advantage?
The Contexta Decision Flip Test
For this deliberately simple one-year screening convention:
Break-even monthly delay cost = annual power-cost gap ÷ delay-month gap
So:
$24.1995M ÷ 30 months ≈ $806,650/month
If the assumed value of delay is above roughly $806,650 per month, Site B’s 30-month schedule advantage becomes larger than Site A’s one-year electricity-cost advantage in this simplified comparison.
This is not a market benchmark.
It is a decision threshold created by the assumptions.
Change the assumptions and the threshold moves.
That is the point of the calculator.
It should not tell us which site always wins.
It should show us what has to change before the decision flips.
Complete Python File
The complete file below reproduces the base calculation, PUE sensitivity graph, two-site comparison and break-even delay threshold.
Save it as ai_data_center_power_cost_calculator.py.
from dataclasses import dataclass
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
HOURS_PER_YEAR = 8_760
@dataclass(frozen=True)
class DataCenterCase:
name: str
it_capacity_mw: float
average_load_factor: float
pue: float
electricity_price_per_mwh: float
grid_connection_delay_months: float = 0.0
monthly_delay_cost: float = 0.0
def calculate_case(case: DataCenterCase) -> dict:
average_it_load_mw = (
case.it_capacity_mw
* case.average_load_factor
)
average_facility_load_mw = (
average_it_load_mw
* case.pue
)
annual_energy_mwh = (
average_facility_load_mw
* HOURS_PER_YEAR
)
annual_electricity_cost = (
annual_energy_mwh
* case.electricity_price_per_mwh
)
delay_cost = (
case.grid_connection_delay_months
* case.monthly_delay_cost
)
screening_cost = (
annual_electricity_cost
+ delay_cost
)
return {
"average_it_load_mw": average_it_load_mw,
"average_facility_load_mw": average_facility_load_mw,
"annual_energy_mwh": annual_energy_mwh,
"annual_electricity_cost": annual_electricity_cost,
"delay_cost": delay_cost,
"screening_cost": screening_cost,
}
def print_case(case: DataCenterCase) -> None:
result = calculate_case(case)
print(f"\n{case.name}")
print(
"Average IT load: "
f"{result['average_it_load_mw']:,.1f} MW"
)
print(
"Average facility load: "
f"{result['average_facility_load_mw']:,.1f} MW"
)
print(
"Annual electricity use: "
f"{result['annual_energy_mwh']:,.0f} MWh"
)
print(
"Annual electricity cost: "
f"${result['annual_electricity_cost']:,.0f}"
)
print(
"Illustrative delay cost: "
f"${result['delay_cost']:,.0f}"
)
print(
"Illustrative screening cost: "
f"${result['screening_cost']:,.0f}"
)
def plot_pue_sensitivity(
base_case: DataCenterCase,
output_dir: Path,
) -> None:
pue_values = np.arange(1.10, 1.61, 0.05)
annual_costs_million = []
for changed_pue in pue_values:
changed_case = DataCenterCase(
name=base_case.name,
it_capacity_mw=base_case.it_capacity_mw,
average_load_factor=base_case.average_load_factor,
pue=float(changed_pue),
electricity_price_per_mwh=(
base_case.electricity_price_per_mwh
),
)
annual_costs_million.append(
calculate_case(changed_case)[
"annual_electricity_cost"
]
/ 1_000_000
)
plt.figure(figsize=(10, 6))
plt.plot(
pue_values,
annual_costs_million,
marker="o",
)
plt.xlabel("Power Usage Effectiveness (PUE)")
plt.ylabel(
"Annual electricity cost (USD million)"
)
plt.title(
"A Higher PUE Raises Annual Electricity Cost"
)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(
output_dir / "pue_cost_sensitivity.png",
dpi=180,
)
plt.close()
def plot_site_comparison(
site_a: DataCenterCase,
site_b: DataCenterCase,
output_dir: Path,
) -> None:
cases = [site_a, site_b]
labels = [case.name for case in cases]
annual_cost = [
calculate_case(case)["annual_electricity_cost"]
/ 1_000_000
for case in cases
]
delay_cost = [
calculate_case(case)["delay_cost"]
/ 1_000_000
for case in cases
]
x = np.arange(len(cases))
width = 0.35
plt.figure(figsize=(10, 6))
plt.bar(
x - width / 2,
annual_cost,
width,
label="Annual electricity cost",
)
plt.bar(
x + width / 2,
delay_cost,
width,
label="Illustrative delay cost",
)
plt.xticks(x, labels)
plt.ylabel("USD million")
plt.title("Cheap Power vs Fast Power")
plt.legend()
plt.tight_layout()
plt.savefig(
output_dir / "site_cost_comparison.png",
dpi=180,
)
plt.close()
def break_even_monthly_delay_cost(
site_a: DataCenterCase,
site_b: DataCenterCase,
) -> float | None:
delay_month_gap = (
site_a.grid_connection_delay_months
- site_b.grid_connection_delay_months
)
if delay_month_gap <= 0:
return None
annual_power_cost_gap = (
calculate_case(site_b)[
"annual_electricity_cost"
]
- calculate_case(site_a)[
"annual_electricity_cost"
]
)
return (
annual_power_cost_gap
/ delay_month_gap
)
def main() -> None:
output_dir = Path(".")
base_case = DataCenterCase(
name="Base case",
it_capacity_mw=100,
average_load_factor=0.85,
pue=1.30,
electricity_price_per_mwh=70,
)
site_a = DataCenterCase(
name="Site A: cheap, slow",
it_capacity_mw=100,
average_load_factor=0.85,
pue=1.30,
electricity_price_per_mwh=50,
grid_connection_delay_months=48,
monthly_delay_cost=2_000_000,
)
site_b = DataCenterCase(
name="Site B: costly, fast",
it_capacity_mw=100,
average_load_factor=0.85,
pue=1.30,
electricity_price_per_mwh=75,
grid_connection_delay_months=18,
monthly_delay_cost=2_000_000,
)
for case in [base_case, site_a, site_b]:
print_case(case)
threshold = break_even_monthly_delay_cost(
site_a,
site_b,
)
if threshold is not None:
print(
"\nBreak-even monthly delay cost "
"for this one-year screening convention: "
f"${threshold:,.0f}/month"
)
plot_pue_sensitivity(
base_case,
output_dir,
)
plot_site_comparison(
site_a,
site_b,
output_dir,
)
if __name__ == "__main__":
main()
How to Run It
- Install Python 3.10 or later.
- Save the complete code as
ai_data_center_power_cost_calculator.py. - Install the plotting packages.
python -m pip install matplotlib numpy
Then run:
python ai_data_center_power_cost_calculator.py
The script prints the case results and saves:
pue_cost_sensitivity.pngsite_cost_comparison.png
What the Model Includes—and What It Leaves Out
| Included | Not yet included |
|---|---|
| IT capacity and average load factor | Hourly / seasonal workload profile |
| PUE | Cooling CAPEX, water use and weather dependence |
| Flat screening electricity price | Full utility tariff and contract structure |
| Simple delay cost | Discounted cash flow, revenue ramp and equipment obsolescence |
| Two-site comparison | Grid-upgrade CAPEX, reliability value and expansion options |
Those omissions are not hidden.
They define the next model.
Three Experiments Worth Trying
- Change PUE from 1.30 to 1.20.
How much annual electricity cost disappears? - Raise electricity price from $70 to $100/MWh.
Does efficiency become more valuable? - Reduce load factor from 0.85 to 0.60.
Did the data center become efficient—or did expensive compute simply sit idle?
The third experiment is especially important.
A lower electricity bill is not automatically a better business result.
What Should You Watch Next?
- Definition of MW: IT capacity, utility allocation, facility load or contracted demand?
- Measured vs design PUE: Are we comparing annual operating data with a design target?
- Load factor: Is lower energy use efficiency, low utilization, or workload flexibility?
- Tariff structure: Which charges sit outside the simplified $/MWh input?
- Delay value: What financing, revenue and equipment assumptions produce the monthly delay cost?
- Decision threshold: At what PUE, tariff or connection delay does the preferred site change?
The Main Idea
We began with one label: 100 MW.
Then we discovered that the label was not enough.
The answer depends on a visible chain:
Capacity → Load Factor → PUE → Time → Tariff → Delay
Python is useful because it lets us change one assumption and immediately see the consequence.
The most useful output is not one electricity-cost number. It is knowing which assumption can change the decision.
Continue Reading
- Why Power, Not Chips, May Limit the AI Data Center Boom — the physical problem behind the calculator.
- How to Understand a 100 MW Data Center Power Model — the same calculation without Python.
- The Hidden Bottleneck of the Electric Age — why grid infrastructure moves on a slower clock.
Key Terms
- IT capacity: the maximum electrical capacity assigned to servers, storage and networking equipment in this model
- load factor: average load divided by maximum or rated capacity over a period
- PUE: Power Usage Effectiveness, total data-center facility energy divided by IT-equipment energy
- facility overhead: electricity used by cooling, power conversion, pumps, lighting and other non-IT support systems
- tariff: the rules and charges under which a utility customer pays for electricity service
- demand charge: a charge linked to the customer’s peak or contracted power demand rather than energy use alone
- sensitivity analysis: changing one or more assumptions to see how the model output responds
- scenario input: an assumed value used to explore a possible case rather than a universal measured fact
- break-even threshold: the value at which two modeled choices produce the same comparison result
- grid delay: the time between the desired connection date and the date sufficient electrical service becomes available
Sources
- U.S. Department of Energy — Best Practices Guide for Energy-Efficient Data Center Design — PUE definition and limitations.
- IEA — Energy and AI data product — capacity, PUE, load factor and electricity-consumption variables.
- Lawrence Berkeley National Laboratory — Electricity Rate Designs for Large Loads: Evolving Practices and Opportunities, 2026 Update — large-load tariffs and risk-allocation mechanisms.
- Lawrence Berkeley National Laboratory — United States Data Center Energy Usage Report: 2025 Update — current U.S. data-center energy modeling context.
Status checked September 30, 2026. The Power-Cost Chain, Assumption Ledger, and Decision Flip Test are The Contexta analytical frameworks. The 100 MW cases, $/MWh values and monthly delay costs are illustrative scenario inputs, not project quotations or market averages. The calculator is an educational screening model, not a full utility-tariff or project-finance model.