01 — Overview

The big picture

Every outage we recorded over the period, boiled down to six numbers.

16,561
Unique Outages
from 7,870 readings
37.5 days
Longest Outage
Montréal
18,255
Peak Clients Hit
Laurentides
21.5M
Client-Hours Lost
21,484,058 total
5.0%
On-Time Restorations
within ±1h of estimate
611
Worst Moment
outages at once

02 — Québec Map

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.

Regional reliability map — Québec 17 regions
Least affected region
Nord-du-Québec
102 outages · 72,358 client-hours
⚠️
Most affected region
Outaouais
2017 outages · 3,857,245 client-hours
Top 5 — Most vs Least Reliable Municipalities
Outages and typical duration, by region

03 — Montréal

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 reliability map — Montréal 34 boroughs
🏆
Most reliable borough
Senneville
3 outages · 10.2h median
Most impacted borough
Ahuntsic-Cartierville
153 outages · 6.0h median

Borough rankings

#BoroughOutagesMedian DurationAvg. ClientsETA ±1h
1Ahuntsic-Cartierville1536.0h3173%
2Montréal-Nord966.5h4507%
3Côte-des-Neiges-Notre-Dame-de-Grâce1466.2h3284%
4Verdun916.4h39215%
5Rivière-des-Prairies-Pointe-aux-Trembles1435.8h2402%
6Ville-Marie1275.8h2524%
7Mercier-Hochelaga-Maisonneuve1185.7h3536%
8Saint-Laurent1126.2h2815%
9Le Plateau-Mont-Royal1095.8h2159%
10Rosemont-La Petite-Patrie1105.7h2084%
11Pierrefonds-Roxboro606.3h3350%
12Dorval446.3h5320%
13Le Sud-Ouest666.0h38212%
14Villeray-Saint-Michel-Parc-Extension815.2h3026%
15Saint-Léonard857.5h21712%
16Baie-D'Urfé155.9h15170%
17LaSalle597.7h26311%
18Kirkland318.1h5890%
19Outremont406.7h3390%
20Anjou589.9h1650%
21Côte-Saint-Luc238.0h51812%
22Pointe-Claire577.3h1625%
23Dollard-des-Ormeaux476.6h1668%
24Lachine536.1h12610%
25Sainte-Anne-de-Bellevue105.3h7090%
26Westmount34.9h16720%
27Mont-Royal254.6h1680%
28L'Île-Bizard-Sainte-Geneviève208.1h6814%
29Beaconsfield166.0h1810%
30Montréal-Est115.6h2820%
31Hampstead249.9h177%
32Senneville310.2h200%
33L'Île-Dorval19.1h8
Montréal — outage duration distribution

04 — Restoration ETA Accuracy

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.

Promised ETA vs actual restoration time
How far off were the estimates?
ETA accuracy by region
Most accurate region
Bas-Saint-Laurent
Mean error · 3.53h
🕐
Least accurate region
Estrie
Mean error · 11.4h

05 — Records

Record holders

The outages that stood out — longest, biggest, fastest fix, best and worst estimates.

Longest Outage
37.5 days
Montréal · started 2026-04-23 11:17
👥
Most Clients Affected
18,255 clients
Laurentides · 2026-05-17 06:38
Fastest Restoration
0.30 hours
Laval · 2026-05-09 07:47
Best ETA Accuracy
Bas-Saint-Laurent
Mean error: 3.53h
🕐
Least Reliable ETA
Estrie
Mean error: 11.4h

06 — Timing

When do outages happen?

What hours and days power tends to fail, and how many outages run at the same time.

Active outages over time
Outage starts by hour and weekday
Outage start hour by cause

07 — Causes

Why does the power go out?

What Hydro-Québec blames — when it records a reason at all (it leaves most blank).

Cause breakdown
Outage duration by cause
Causes by administrative region

08 — Collected Data

How solid is this data?

How much we collected, how continuously, and what it adds up to.

📅
First Record
2026-04-07 03:59
(UTC)
📅
Last Record
2026-06-01 23:56
(UTC)
⏱️
Collection Period
55.8 days
1339 hours
📸
Snapshots Collected
7,870
141.0/day avg.
🎯
Coverage Rate
98.5%
1,321/1,341 hours collected
🕳️
Collection Gaps
3
largest 21.0h
Unique Outages Found
16,561
99.6% resolved
🏙️
Affected Municipalities
1,280
18 regions
🗺️
Montréal Boroughs
33
with data
Typical Outage Duration
6.57h
median · typical clients: 11
👥
Total Client-Hours
21,484,058
cumulative human impact
📊
Outages with ETA data
6,437
out of 16,561 outages
🔍
Top Identified Cause
Planned/Maintenance
3,651 outages (blanks excluded)

09 — Methodology

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.

10 — Data dictionary

What each value means

Plain-language definition of every metric in this report and how it is computed.

ValueMeaningHow it's computed
Unique outagesDistinct power outages over the period.Readings merged by (start time, GPS location).
Reading / snapshotOne capture of the live outage list.Saved when HQ publishes a change (~10 min), then deduplicated.
Clients affectedCustomers (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-hoursTotal human impact: people × time without power.Clients affected × duration (h), summed.
Reliability score0–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 simultaneousMost outages active at the same moment.Max outage count across all readings.
Coverage rateShare of hours we were actually collecting.Hours with ≥1 reading ÷ total hours in the period.
Collection gapsStretches with no readings (collector downtime).Count of jumps > 30 min between readings.
Cause: plannedScheduled/maintenance work, not a failure.HQ cause codes for maintenance, works and pruning.
Cause: unknownNo cause published by HQ.Blank cause code in the feed (~⅔ of outages).

11 — About this project

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.

12 — How it's built

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 JSONL file 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 (httpx for fetching, pandas for analysis, shapely for region/borough lookup, plotly + folium for charts and maps, Jinja2 for this page) and the Google Cloud Storage SDK. Linted with flake8, type-checked with mypy.
  • Docker. The collector ships with a Dockerfile and docker-compose.yml, so it runs the same way on a laptop or a server.