gCO2/kWh 7 SDG 7 · affordable and clean energy
7SDG 7 · affordable and clean energy

GB carbon intensity forecast

deployed
API live
Since March 2025 Cadence 30 min Region GB

A half-hourly forecast of UK grid carbon intensity you can actually run a dishwasher against. Trained on 4.2M rows of half-hourly grid data; deployed on a K3s cluster behind a tiny FastAPI service.

forecast horizon:
last refreshed
P10 — optimistic
g/kWh
next 30-min period
P50 — median
g/kWh
next 30-min period
P90 — pessimistic
g/kWh
next 30-min period
Quantile forecast — P10 / P50 / P90 uncertainty bands
P10–P90 band P50 median P10 lower P90 upper
LightGBM quantile regression
P10 / P50 / P90 outputs
30-min settlement periods
Deployed on Cloud Run
02 · how it works

From the National Grid to your dishwasher

Five stages, retrained nightly. Each box is a small thing that does one job, and fails loudly when it cannot.

01 · INGEST

Data

NESO API, REST, 5-min cron. Generation mix, demand, interconnector flow.

REST 5-min cron
02 · FEATURES

Engineering

Lags, rolling means, ECMWF wind & temperature forecasts. pandas, DuckDB.

pandas DuckDB
03 · MODEL

Quantile regressor

LightGBM, pinball loss, P10/P50/P90. Retrained nightly. MLflow tracking.

LightGBM MLflow
04 · API

Forecast service

FastAPI on Cloud Run. Cached 30s. Returns JSON quantiles by horizon.

FastAPI Cloud Run
05 · SURFACE

You

This widget, an iOS shortcut, Home Assistant. Open API, CC-BY 4.0.

Public CC-BY 4.0
Cadence
Retrain nightly · 02:30 UTC
Latency
p95 182 ms end-to-end
Window
30-min × up to 48 horizons
Monitoring
Pinball loss, drift, freshness
03 · explainability

What is the model actually doing?

Three diagnostics I check when something looks off. Same figures used internally, embedded straight from the training notebook.

Fig. 1 · Feature importance (gain)

Lagged demand and wind dominate

Top 10 features by total gain across all three quantile boosters. demand_lag_30m and wind_forecast_3h together account for ~58% of split gain — unsurprising given GB's 30 GW of wind capacity.

Fig. 2 · Calibration

Quantiles hold, just

Empirical coverage of the P10–P90 band over the last 90 days, by hour-of-day. Slight under-coverage between 17:00 and 20:00 — peak demand period, where the model is least confident.

Fig. 3 · Residuals over horizon

Error grows non-linearly

Mean absolute pinball loss vs forecast horizon, last 30 days. Roughly flat to 4 hours, then climbs steeply — this is why the default horizon button is 4 hours.

04 · stack & source

Built with boring, observable parts

No exotic dependencies. Everything here has been in production somewhere for at least five years. That's the point.