This dashboard analyzes California (CAISO) grid conditions to evaluate how flexible data center load profiles affect grid utilization, reliability, cost, and emissions. The core thesis:
Data centers that shift load to follow solar generation ("camel" profiles) improve grid utilization, reduce electricity costs, absorb renewable surplus, and lower marginal emissions — compared to flat or night-heavy profiles.
Virginia passed a bill incorporating a grid utilization factor to encourage better use of existing capacity before building new infrastructure. Data center operators seeking faster interconnection can demonstrate they improve grid utilization through flexible load profiles. This dashboard quantifies that value proposition using real CAISO data.
| Property | Details |
|---|---|
| Source | CAISO day-ahead demand forecast |
| File | demand_forecast.json |
| Format | Daily entries keyed by date ("YYYY-MM-DD"), each containing a 24-element array of hourly demand in MW |
| Coverage | Jan 1, 2020 – Dec 31, 2025 (2,192 days) |
| Missing data | Null values treated as 0 MW |
| Property | Details |
|---|---|
| Source | Derived from CAISO resource adequacy filings and installed capacity data |
| File | available_capacity.json |
| Format | Nested by year → month → resource type → 24-hour array (MW) |
| Resource types | Nuclear, Geothermal, Biomass, Other Thermal, Gas CCGT, Gas Peaker, Gas Steam, Gas ICE, Hydro, Wind, Solar, Battery Storage |
Key assumption: Monthly average hourly profiles — the same 24-hour profile is used for every day within a given month. This does NOT capture day-to-day weather variability. Solar profiles reflect monthly capacity factors (zero at night, peak at solar noon). Battery Storage is excluded from total available capacity (treated as load modifier, not supply).
| Property | Details |
|---|---|
| Source | CAISO Day-Ahead Market, DLAP (Default Load Aggregation Point) nodes |
| File | caiso_prices.json |
| Weighting | Load-weighted across 3 utility zones: PG&E (43.5%), SCE (43.5%), SDG&E (13%) |
| Components | LMP = MEC (Marginal Energy) + MCC (Congestion) + Loss + GHG |
| Coverage | ~2,170 of 2,192 days have price data |
| Property | Details |
|---|---|
| Source | EIA (U.S. Energy Information Administration) |
| Resolution | Monthly ($/MCF) |
| Usage | Normalizing LMP and MEC to remove gas price variation, creating an implied heat-rate proxy |
| Coverage | Jan 2020 – Dec 2025 |
Reserves model California's operating reserve obligations. The requirement is the greater of a percentage of demand or a floor value:
| Period | Hours | Reserve % |
|---|---|---|
| Peak | 4–9 PM (h=16–21) | 8.4% |
| Shoulder | 6–9 AM, 9–11 PM (h=6–9, h=21–23) | 7.7% |
| Off-peak | All other hours | 7.0% |
Simplification: Actual CAISO procurement uses Regulation Up/Down, Spinning Reserve, and Non-Spinning Reserve with different requirements. The 3,500 MW floor approximates California's typical minimum reserve margin.
The key reliability metric — how much spare capacity exists above demand and reserves:
headroom_dc[h] = available[h] - (demand[h] + dc_load[h]) - reserve_with_dc[h]Demand minus non-gas generation — the residual load that gas plants must serve:
Used in the LMP vs Net Load scatter chart to show how electricity prices respond to the gas fleet's workload.
All profiles deliver the same total daily energy (avgMw × 24 MWh) for fair comparison. This is critical: no profile "cheats" by consuming less total energy.
Constant load at all hours. The simplest profile and the baseline for comparison.
Where:
SOLAR_NORM[month][h] = SOLAR_CF[month][h] - mean(SOLAR_CF[month]) (mean-centered solar shape)flex ∈ [0, 1.0] — controls how aggressively load follows solarmax(0, ...) ensures no negative loadThe opposite of camel — shifts load away from solar hours into evening and night. Represents a traditional data center pattern that ramps up when electricity demand is highest.
After the max(0, ...) clipping, the total energy may not equal avgMw × 24. A post-clipping rescaling step corrects this:
target = avgMw × 24
actual_sum = sum(raw[0..23])
scale = target / actual_sum
profile[h] = raw[h] × scale
This is particularly important for the night-heavy profile in summer months, where max(0, ...) clips solar-hour values to zero.
The SOLAR_CF profiles (12 months × 24 hours) are derived from California solar capacity factor data:
What it shows: Stacked area chart of each generation resource's available capacity (24 hours) overlaid with a demand line.
How to read it:
Key insight: On sunny spring days with low demand, solar pushes total capacity far above demand — this is where overgeneration and negative prices occur.
What it shows: For each hour of the day, the distribution of effective headroom across all days in the dataset.
Bands:
Key insight: Headroom is tightest during evening peak hours (5–8 PM) when solar drops off but demand stays high. The p5 line dipping toward or below zero means 5% of days have dangerously low spare capacity at that hour.
What it shows: Each dot is one hour from the dataset. X-axis = net load (demand minus all non-gas generation), Y-axis = LMP (wholesale electricity price).
Color: Time of day (yellow = daytime solar hours, blue/purple = night hours)
Dot size: Scaled by CA natural gas citygate price — larger dots = more expensive gas months
Key insight: When net load is negative (surplus), LMP drops to zero or negative — the grid is paying to offload excess generation. When net load is high, LMP rises sharply as expensive peaker plants come online. Gas price shifts the entire curve vertically.
What it shows: The baseline headroom percentile bands (shaded, from the chart above) with additional dashed lines showing the median headroom after adding each data center profile.
Profile lines:
Key insight: The camel profile's line stays closest to the baseline during evening peak hours (4–9 PM) because it consumes less at those times, preserving reliability when it matters most.
What it shows: Color-coded stat cards comparing Baseline, Flat, Camel, Night-Heavy, and Custom profiles across three metrics:
| Metric | Formula | What it means |
|---|---|---|
| Avg Utilization | mean((demand + dc_load) / available) |
How efficiently grid capacity is used. Higher = better utilization of existing infrastructure. |
| Min Headroom (p5) | 5th percentile of all hourly headroom values | Worst-case reliability. The headroom level that only 5% of hours fall below. |
| Stress Hours | Count of hours where headroom < 3,500 MW | How often the grid is dangerously tight. Fewer = better. |
Arrows: Green up-arrows indicate improvement vs baseline; red down-arrows indicate degradation.
Key insight: The camel profile increases utilization (good) while adding fewer stress hours than the flat or night-heavy profiles.
Methodology: Empirical LMP-Headroom Model
Unlike a simple weighted average that assumes prices don't change when load is added, this analysis uses an empirical relationship learned from 6 years of CAISO data to model how adding DC load shifts grid headroom and thereby affects LMP.
A naive approach would compute: cost = Σ(dc_load[h] × historical_LMP[h]) / Σ(dc_load[h]). This produces misleading results because:
Result: All DC profiles would show nearly identical costs (~$35/MWh), with no price signal for flexibility value.
We extracted the empirical relationship between effective headroom and LMP from ~52,080 hourly observations (2020-2025):
Step 1: Define 6 headroom bins (based on scatter plot analysis)
| Bin | Headroom Range (GW) | Grid Condition |
|---|---|---|
| 0 | < 0 | Scarcity (load shedding risk) |
| 1 | 0–5 | Very Tight (peakers running) |
| 2 | 5–10 | Tight (high stress) |
| 3 | 10–20 | Moderate (normal operations) |
| 4 | 20–30 | Comfortable (baseload only) |
| 5 | ≥ 30 | Abundant (possible curtailment) |
Step 2: Normalize LMP by gas price
Removes gas price volatility (2020-2021: ~$2-3/MCF vs 2022: ~$7-9/MCF) to extract the structural relationship between headroom and pricing.
Step 3: Build 24×6 lookup matrix
For each hour-of-day (0-23) and headroom bin (0-5):
This captures:
For each day with price data and each hour:
Baseline (No DC):
With DC Profile:
Note: Reserves are recomputed with DC load since they scale with total demand.
Bar chart: Single bar per profile showing adjusted LMP ($/MWh). No component breakdown (MEC/MCC/Loss/GHG) because the lookup table provides total LMP only.
Baseline bar: Simple average LMP under historical grid conditions (no DC load). Provides reference for what grid prices were before any DC is added.
Stat cards below: Show per-profile $/MWh, annual cost ($M/year), and savings vs Flat (not Baseline). Color borders match profile colors.
| Profile | Typical Cost | Why? |
|---|---|---|
| Baseline | $38-42/MWh | Average grid LMP with no DC (reference point) |
| Flat | $40-45/MWh | Reduces headroom uniformly at all hours |
| Camel | $28-35/MWh | Loads during surplus hours (high headroom → low LMP) |
| Night-Heavy | $55-75/MWh | Loads during tight evening hours (low headroom → high LMP) |
Economic justification for flexible load: A 500 MW solar-following DC saves $10-15M/year compared to flat profile, purely from avoiding high-LMP hours. At 5,000 MW, night-heavy profiles spike to $100-150/MWh as they push the grid into scarcity bins.
Limitations:
How it works:
Color scale:
Tabs: Switch between Baseline, +Flat DC, +Camel DC, +Night DC, and +Custom DC to see how each profile changes the heatmap pattern. Hover over any cell for exact headroom values.
Summary cards: Show average minimum headroom, worst single hour, and stress hour count for the selected profile — all computed on the 100 stress days only.
What is surplus? Hours when all non-gas generation exceeds demand:
Where non_gas_gen = Solar + Wind + Hydro + Nuclear + Geothermal + Biomass + Other Thermal.
When surplus > 0, even with ALL gas plants shut off, the grid overproduces. This energy is typically curtailed (mostly solar).
Chart: Monthly bar chart showing surplus (gray line) and how much each DC profile absorbs (colored bars). Values are annualized (divided by years of data).
Absorption formula:
Camel DCs absorb the most because they peak during solar hours — exactly when surplus is highest.
Limitations: Available capacity ≠ actual generation. CAISO's 2025 curtailment was ~92% transmission-constrained (3.12 of 3.4 TWh) — our model captures only oversupply-driven surplus. No imports/exports or battery dispatch are modeled.
Methodology: Dispatch-Stack Proxy
For each hour, we determine the marginal generator by walking the gas merit order:
gasResidual = max(0, demand - nonGasGen)| Gas Type | Heat Rate (MMBtu/MWh) | CO² Rate (tCO²/MWh) |
|---|---|---|
| CCGT | 7.0 | 0.41 |
| Steam | 9.5 | 0.55 |
| ICE | 8.5 | 0.50 |
| Peaker | 10.8 | 0.63 |
Rates derived from standard heat rates × EPA emission factor for natural gas (53.06 kg CO²/MMBtu).
Chart (dual axis):
Key insight: During solar hours, marginal emissions are near zero because the next MW of load displaces RE curtailment rather than causing additional gas combustion. Camel DCs consume most energy during these low-emission hours, making them the cleanest option per MWh consumed.
Stat cards: Show per-profile weighted average emission rate (tCO²/MWh), annual CO² (ktCO²/yr), and savings vs Flat.
Purpose: While preset profiles (Flat, Camel, Night-Heavy) demonstrate general patterns, this calculator finds the theoretically best load allocation across all 24 hours for each day, given real grid conditions and empirical LMP-headroom relationships.
For a data center of size avgMw, the optimizer allocates avgMw × 24 MWh/day of energy across 24 hours to minimize cost:
optLoad[h] = 0 for all hours (h = 0..23)Larger increments for bigger DCs reduce computation time while maintaining accuracy.
sum(optLoad) ≈ avgMw × 24:
h:
optLoad[h] + INCREMENT_MW > 3 × avgMw (hourly capacity constraint)testDemand[h] = demand[h] + optLoad[h] + INCREMENT_MWtestReserves = max(0.06 × max(testDemand), 3500)headroom = available[h] - testDemand[h] - testReserves[h]LMP[h][bin(headroom)]cost = INCREMENT_MW × LMPh* with lowest marginal costoptLoad[h*] += INCREMENT_MWHourly capacity constraint: No single hour can exceed 3× avgMw. This prevents unrealistic concentration (e.g., allocating all 24h of energy to a single hour). For a 4,500 MW DC, max hourly load = 13,500 MW.
The greedy approach (always choosing the lowest-cost hour for the next increment) is near-optimal because:
Chart: Dual-bar chart showing:
The chart's y-axis is fixed across all dates (set to 1.2× the maximum hourly load across all optimized days) to make day-to-day variation visible.
Missing data warning: If a date is missing demand, capacity, or price data (~22 of 2,192 days), the purple bars show the average profile and a warning appears. This ensures consistent visualization.
Scorecard: Four cost comparison cards:
Each card shows:
Typical computation times (client-side JavaScript):
| DC Size | Increments per Day | Total Iterations | Time |
|---|---|---|---|
| 500 MW | 240 | ~520k | 3-5 sec |
| 2,000 MW | 480 | ~1.0M | 8-12 sec |
| 5,000 MW | 600 | ~1.3M | 15-20 sec |
Computation is opt-in (triggered by "Calculate" button) to avoid slowing down the main dashboard.
Click the "Custom" preset button to open the interactive profile editor. This adds a 4th profile alongside Flat, Camel, and Night-Heavy, allowing direct comparison of any arbitrary load shape against the presets.
Since sum(customMultipliers) = 24, total daily energy is always avgMw × 24 MWh.
After each draw stroke (mouseup):
This ensures energy preservation regardless of the shape you draw. The "Reset to Flat" button restores all multipliers to 1.0.
| # | Assumption | Impact |
|---|---|---|
| 1 | Monthly average capacity profiles applied to all days | Overestimates surplus on cloudy days, underestimates on clear days |
| 2 | No battery/storage dispatch modeled | Underestimates real-world surplus absorption |
| 3 | No import/export flows | CAISO exports surplus to neighbors; our model assumes autarky |
| 4 | Simplified reserve model (%-of-demand + floor) | Approximation of CAISO's actual procurement |
| 5 | DLAP load-weighted LMP (PG&E 43.5%, SCE 43.5%, SDG&E 13%) | Smooths out locational price extremes |
| 6 | DC is price-taker (no market impact) | Reasonable up to ~500 MW; large DCs would affect prices |
| 7 | Solar CF profiles are fixed monthly averages | No cloud/weather variability captured |
| 8 | Analysis is CAISO-specific | Virginia/PJM would need different data, different generation mix |
| 9 | Time period: 2020–2025 | Includes COVID demand anomaly (2020), Texas freeze (Feb 2021), summer heat events |
| 10 | Hydro treated as inflexible in surplus calculation | Partially justified by spring snowmelt; overstates surplus in dry months |
| 11 | Simplified gas merit order for emissions | Real CAISO dispatch uses offer-based optimization, not a fixed stack |
| 12 | No imported emissions modeled | CAISO imports significant energy from neighboring regions |
| 13 | Static emission rates per gas type | Real rates vary with plant efficiency curves and ambient conditions |
| Metric | Our Model | Real-World Reference | Notes |
|---|---|---|---|
| Annual surplus | ~3.1 TWh/yr | CAISO curtailed ~3.4 TWh (2025) | Close match, but different mechanism mix |
| Peak demand | ~45–52 GW | CAISO record: 52.1 GW (Sep 2022) | Data captures this |
| Min headroom | Can go negative | CAISO issues Flex Alerts when tight | Model captures stress periods |
| LMP range | -$100 to $1,000+/MWh | CAISO prices have gone negative and spiked >$1,000 | Verified for specific dates |
To verify any specific calculation from the dashboard:
demandData["2023-08-15"] → 24-element arraycapacityData["2023"]["08"] → resource arrayssum(all resources except Battery)[h] - demand[h] - max(3500, demand[h] × 0.084)priceData["2023-08-15"]["14"] → {LMP, MEC, MCC, Loss, GHG}dc_load[h] × LMP[h] for several hours, compare to displayed averageThe dashboard pre-computes these across all 2,192 days. Any individual data point can be verified against the raw JSON files.
| Source | What It Provides | Why It Matters |
|---|---|---|
| EIA Hourly Generation (EIA-930) | Actual hourly generation by fuel type | Replaces capacity-based proxy with real generation data |
| CAISO Curtailment Data | Actual hourly curtailment by resource | Ground truth for surplus/curtailment analysis |
| WattTime MOER | Marginal Operating Emissions Rate | Real marginal emission rates by grid region and hour |
| PJM Data (Virginia) | PJM hourly prices, generation, capacity | Enables analysis for Virginia data centers (where the utilization bill passed) |