The Grid Is the Real AI Infrastructure

AI data centers depend on regional electricity systems. This companion to The Buildings Behind AI explores that dependence through illustrative weekly scenarios. Pick a region and a week to compare generation, demand and the forecast, then find the hours with the smallest margin.

Power under the models · ERCOT

The grid is the real AI infrastructure

Electric Reliability Council of Texas. West Texas and Central Texas cloud build-out. Compare the sources of electricity with the changing demand and the margin left over through the week.

SNAPSHOT · ERCOT2026-07-08 04:00 CTHeat peak
Showing a fixed ERCOT week (saved 2026-07-10T18:00:00-05:00). Not a live feed.

A hot week. Demand runs above the day-ahead forecast into the evening, and spare capacity gets thin—even while gas and solar rearrange under the stack.

ERCOT, last hour in view: demand 53,506 MW, spare capacity about +1.6%, mostly Natural gas (47%), 12,455 MW below the day-ahead forecast.

Demand-12,455 MW vs forecast
53.5KMW
ERCOT, last hour in view: demand 53,506 MW, spare capacity about +1.6%, mostly Natural gas (47%), 12,455 MW below the day-ahead forecast.
Spare capacityRough, from public series
+1.6%
Higher is more comfortable. See the methods note for what this number is and is not.
Largest fuelNatural gas
47%
Natural gas is the largest share of generation.

Demand versus forecast

Amber = hotter than forecast · cyan = cooler
ERCOT: demand versus day-ahead forecast
Where load ran high or low against what the day-ahead schedule expected
Skip to data table
ERCOT, last hour in view: demand 53,506 MW, spare capacity about +1.6%, mostly Natural gas (47%), 12,455 MW below the day-ahead forecast.

What is generating

Stacked by fuel · not emissions
Skip to data table
Fuel mix over time. This is not a real-time carbon score.

Spare capacity over the week

Brush the strip below to zoom
Skip to data table
Brush the lower strip to focus part of the week.

Tightest hours

Hatched bars are the danger band · color is not the only cue
Skip to data table
Worst hours first.

How to read spare capacity

  • Comfortable · 20% or more
  • Moderate · 12% to 20%
  • Watch · 5% to 12%
  • Tight · under 5% (hatched)

The scenarios use fixed, illustrative data patterned after EIA Hourly Grid Monitor series. Here, spare capacity means generation plus imports minus demand, divided by demand. It helps compare tight and comfortable hours within the example; it is different from an operator’s official contingency-reserve measure. The calculation helpers are available in semiotic/recipes.

Why these charts (and what the suggestion engine picks)

This drawer shows which charts Semiotic recommends for the demand-and-forecast table, along with a text description of the comparison.

  1. CalendarHeatmapRecipe — score 3.25 · Strong fit for change-detection (3/5)
  2. EventDropChart — score 3.00 · Strong fit for change-detection (3/5)
  3. Scatterplot · [object Object] — score 0.60 · x = demandMw, y = t
  4. BubbleChart — score 0.60 · x = demandMw, y = t
A difference chart of y by t. This is a trend chart; read it for the overall direction of y.

Fields it noticed:demandMw, t, forecastMw

Regions: ERCOT, CAISO, PJM, NYISO · 5 weeks to replay · companion to The Buildings Behind AI

JSX
import { stackFuelSeries, demandForecastRows, reserveSeries, thresholdBandsForReserve, summarizeOperatingPoint, gridEventAnnotations, } from "semiotic/recipes" import { applyAnnotationLifecycle } from "semiotic/ai" import { DifferenceChart, StackedAreaChart, MinimapChart } from "semiotic" import { BarChart } from "semiotic/ordinal" import { BigNumber } from "semiotic/value" // Pure helpers turn BA hours into chart-ready series — agents import the same // pipeline, not a 2k-line page fork. const fuelStack = stackFuelSeries(hours) // StackedAreaChart const demandForecast = demandForecastRows(hours) // DifferenceChart a/b const reserves = reserveSeries(hours) // Minimap + risk bars const operating = summarizeOperatingPoint(hours) const styleRules = thresholdBandsForReserve({ tight: 5, watch: 12, comfortable: 20 }) const annotations = applyAnnotationLifecycle( gridEventAnnotations(events), { dataExtent: [hours[0].t, hours.at(-1).t] }, ) <DifferenceChart data={demandForecast} xAccessor="t" seriesAAccessor="a" seriesBAccessor="b" seriesALabel="Demand" seriesBLabel="Forecast" seriesAColor="var(--semiotic-warning)" seriesBColor="var(--semiotic-info)" /> <StackedAreaChart data={fuelStack} xAccessor="t" yAccessor="mw" areaBy="fuel" colorScheme={FUEL_COLOR_MAP} /> <BarChart data={tightestHours} categoryAccessor="label" valueAccessor="reserveMarginPct" styleRules={styleRules} // hatch on the tight band />