The big picture
Every outage we recorded over the period, boiled down to six numbers.
Reliability across Québec's regions
Every administrative region is shaded by its reliability score: green regions had the fewest client-hours lost to outages, red the most. Hover a region for its numbers.
Inside Montréal
Every borough and linked city on the island, shaded by reliability score (green = fewest client-hours lost, red = most). Hover a borough for its numbers.
Borough rankings
| # | Borough | Outages | Median Duration | Avg. Clients | ETA ±1h |
|---|---|---|---|---|---|
| 1 | Ahuntsic-Cartierville | 153 | 6.0h | 317 | 3% |
| 2 | Montréal-Nord | 96 | 6.5h | 450 | 7% |
| 3 | Côte-des-Neiges-Notre-Dame-de-Grâce | 146 | 6.2h | 328 | 4% |
| 4 | Verdun | 91 | 6.4h | 392 | 15% |
| 5 | Rivière-des-Prairies-Pointe-aux-Trembles | 143 | 5.8h | 240 | 2% |
| 6 | Ville-Marie | 127 | 5.8h | 252 | 4% |
| 7 | Mercier-Hochelaga-Maisonneuve | 118 | 5.7h | 353 | 6% |
| 8 | Saint-Laurent | 112 | 6.2h | 281 | 5% |
| 9 | Le Plateau-Mont-Royal | 109 | 5.8h | 215 | 9% |
| 10 | Rosemont-La Petite-Patrie | 110 | 5.7h | 208 | 4% |
| 11 | Pierrefonds-Roxboro | 60 | 6.3h | 335 | 0% |
| 12 | Dorval | 44 | 6.3h | 532 | 0% |
| 13 | Le Sud-Ouest | 66 | 6.0h | 382 | 12% |
| 14 | Villeray-Saint-Michel-Parc-Extension | 81 | 5.2h | 302 | 6% |
| 15 | Saint-Léonard | 85 | 7.5h | 217 | 12% |
| 16 | Baie-D'Urfé | 15 | 5.9h | 1517 | 0% |
| 17 | LaSalle | 59 | 7.7h | 263 | 11% |
| 18 | Kirkland | 31 | 8.1h | 589 | 0% |
| 19 | Outremont | 40 | 6.7h | 339 | 0% |
| 20 | Anjou | 58 | 9.9h | 165 | 0% |
| 21 | Côte-Saint-Luc | 23 | 8.0h | 518 | 12% |
| 22 | Pointe-Claire | 57 | 7.3h | 162 | 5% |
| 23 | Dollard-des-Ormeaux | 47 | 6.6h | 166 | 8% |
| 24 | Lachine | 53 | 6.1h | 126 | 10% |
| 25 | Sainte-Anne-de-Bellevue | 10 | 5.3h | 709 | 0% |
| 26 | Westmount | 3 | 4.9h | 1672 | 0% |
| 27 | Mont-Royal | 25 | 4.6h | 168 | 0% |
| 28 | L'Île-Bizard-Sainte-Geneviève | 20 | 8.1h | 68 | 14% |
| 29 | Beaconsfield | 16 | 6.0h | 181 | 0% |
| 30 | Montréal-Est | 11 | 5.6h | 282 | 0% |
| 31 | Hampstead | 24 | 9.9h | 17 | 7% |
| 32 | Senneville | 3 | 10.2h | 20 | 0% |
| 33 | L'Île-Dorval | 1 | 9.1h | 8 | — |
Does the power come back when they say it will?
ETA means estimated time of restoration — the time Hydro-Québec announces for when the power should be back. For every resolved outage, we compared that promise to the moment power actually returned. In the chart below, each dot is one outage: the dashed line is a perfect estimate, dots above it took longer than promised (red), dots below came back sooner (green). The “±1h” figure means the outage was restored within one hour of the promised time.
Record holders
The outages that stood out — longest, biggest, fastest fix, best and worst estimates.
When do outages happen?
What hours and days power tends to fail, and how many outages run at the same time.
Why does the power go out?
What Hydro-Québec blames — when it records a reason at all (it leaves most blank).
How solid is this data?
How much we collected, how continuously, and what it adds up to.
How this report is produced
- Source: Hydro-Québec public outage feed — the live marker list plus the affected-zone polygons (KMZ).
- Period: 2026-04-07T03:59 → 2026-06-01T23:56.
- Readings: a reading is saved only when Hydro-Québec publishes a change (≈ every 10 min), then deduplicated. 7870 readings → 16561 distinct outages.
- One outage = one
(start time, GPS location). Repeated readings of the same outage are merged; client count is its observed peak. - Duration = Hydro-Québec's reported start time → restoration (last reading the outage appeared in). When the reported start predates collection, the first time we observed it is used instead.
- Client-hours = clients affected × duration (hours). The core measure of human impact.
- Reliability score (0–10) ranks each area against the others by outage frequency (40%), typical duration (30%) and client-hours (30%); 10 = best. Percentile ranking is used so a few extreme outages don't flatten the scale.
- Regions & boroughs are assigned by exact point-in-polygon test against official Québec region and Montréal borough boundaries — the same polygons drawn on the maps.
- Municipality names: Hydro-Québec's feed identifies municipalities only by an internal code with no public name table, so areas are reported by region/borough; only municipalities with a confirmed name are listed individually.
- ETA accuracy: resolved outages only, comparing Hydro-Québec's first announced restoration time to the actual restoration.
What each value means
Plain-language definition of every metric in this report and how it is computed.
| Value | Meaning | How it's computed |
|---|---|---|
| Unique outages | Distinct power outages over the period. | Readings merged by (start time, GPS location). |
| Reading / snapshot | One capture of the live outage list. | Saved when HQ publishes a change (~10 min), then deduplicated. |
| Clients affected | Customers (meters) without power for an outage. | Peak value HQ reported for that outage. |
| Duration (h) | How long an outage lasted, in hours. | Restoration time − start time. |
| Client-hours | Total human impact: people × time without power. | Clients affected × duration (h), summed. |
| Reliability score | 0–10 comparison of an area's outage burden; 10 = best. | Percentile rank of frequency (40%), duration (30%), client-hours (30%), inverted. |
| ETA accuracy (±1h) | Share of restorations that finished within 1h of HQ's first promise. | Resolved outages where |promised − actual| ≤ 1h. |
| Peak simultaneous | Most outages active at the same moment. | Max outage count across all readings. |
| Coverage rate | Share of hours we were actually collecting. | Hours with ≥1 reading ÷ total hours in the period. |
| Collection gaps | Stretches with no readings (collector downtime). | Count of jumps > 30 min between readings. |
| Cause: planned | Scheduled/maintenance work, not a failure. | HQ cause codes for maintenance, works and pruning. |
| Cause: unknown | No cause published by HQ. | Blank cause code in the feed (~⅔ of outages). |
Why this exists, and a few honest notes
- Where it started. Last winter my power went out. The estimate said two hours, then it slipped to one, then to three — and I spent the whole day in the dark. I wanted to know how reliable the grid really is, where the best and worst places are, and whether those restoration estimates can be trusted. So I collected outage data for about two months to get a meaningful picture.
- Built with AI, end to end. Generative AI helped with the entire project — writing the data collector, deploying it to a server, storing the readings in a Google database, generating this web report, analysing the numbers, and even drafting the article that accompanies it. It's a small example of what one person and AI can build together.
- A wish for Hydro-Québec. It would be genuinely useful if Hydro-Québec offered public visualizations like these — not as criticism, but so people could see the scale and complexity of keeping the lights on across an entire province.
- A funny limitation. When the power goes out at my own apartment, the collector goes dark too — so it can't record its own outage. That happened at least once while I was home, and probably a few other times I never noticed.
- Please read this as illustration. I did my best to keep everything accurate, but this analysis may still contain mistakes and rough interpretations. Treat it as an exploration, not an official source.
Technical setup & how to reproduce it
Everything here was gathered on a personal laptop. The whole stack is small enough to run yourself.
- Where it ran. All the data was collected locally, on my own laptop — a small Python service left running in the background. No cloud server was needed to gather it (though it can be deployed to one for 24/7 uptime — see below).
- What it does. A collector polls Hydro-Québec's public outage feed (the live marker list + the affected-zone polygons), and an analysis step turns the saved data into this self-contained HTML report.
- How often it polls. It checks the feed every 60 seconds, but only saves a new reading when Hydro-Québec actually publishes a change (≈ every 10 min). Requests time out after 30 s, and a failed check is skipped rather than crashing the loop.
- Where data is stored. Readings are appended to one
JSONLfile per hour (pannes_YYYY-MM-DD_HH.jsonl) on the laptop's disk. Each row is one snapshot of the live outage list. - Backup. Once an hour, every closed hourly file is uploaded to a Google Firebase Cloud Storage bucket — the durable copy. The analysis can re-download the full history from there before building a report, so the laptop disk is never the single point of failure.
- Automatic report. This page is generated end-to-end from the raw data: every number, chart, map and table is recomputed at build time, so re-running the pipeline always produces an up-to-date report with no manual editing.
- Stack. Python 3.12 (
httpxfor fetching,pandasfor analysis,shapelyfor region/borough lookup,plotly+foliumfor charts and maps,Jinja2for this page) and the Google Cloud Storage SDK. Linted withflake8, type-checked withmypy. - Docker. The collector ships with a
Dockerfileanddocker-compose.yml, so it runs the same way on a laptop or a server.