
GLOF Monitor - Glacial Lakes Outburst Floods.
Satellite data for South Lhonak Lake was there for years before the 2023 flood. GLOF connects the dots ,Sentinel-2 imagery, NDWI/NDSI processing, a risk engine, and AWS SNS alerts into an automated early-warning pipeline for glacial lake outburst floods.
GLOF
Glacial Lakes Outburst Floods tracker.
Ishan Gupta — Engineering write-up, October 2026
On the night of 3 October 2023, South Lhonak Lake in Sikkim breached its moraine dam. By morning, the Teesta river had swept through Chungthang, destroyed the 1,200 MW hydropower dam, erased bridges, and killed or left missing more than a hundred people. The lake had been swelling visibly for years. Satellites had been watching the entire time. Nobody had connected the dots into an automated warning system.
That is the gap this project tries to close. Glacial Lake Monitor derives water and ice boundaries from Sentinel-2 imagery going back to 2018, evaluates outburst risk on each observation, and dispatches alerts through AWS SNS when a threshold is crossed. The reference case is South Lhonak — deliberately chosen because we know exactly what happened and when.
The problem
A glacial lake outburst flood is caused by the sudden failure of a moraine dam left behind as a glacier retreats. Early-warning systems exist for rainfall floods because we have rain gauge networks, and for tsunamis because we have seismographs. For GLOFs, the only reliable signal is the lake itself — at 5,000 metres in the Himalayas, with no sensor you can walk out to check.
What we do have is ESA's Sentinel-2 constellation, which revisits any point on Earth every five days. The green and near-infrared bands are enough to detect standing water. Add shortwave infrared and you can detect ice. The Level-2A surface reflectance product is distributed free as Cloud-Optimised GeoTIFFs through the AWS Registry of Open Data (RODA) — the same open-data programme that hosts Terrarium elevation tiles, Landsat, and dozens of other public datasets. The data was always there. The pipeline was not.
How we read the tiles: Element 84's Earth Search STAC API indexes every scene. With HTTP range requests against COG tiles, we read just the 5×5 km window around the lake — never a full 800 MB tile. The nine-year South Lhonak archive builds in about five minutes.
The stack
Image processing
For each scene, the pipeline reads four bands: green, NIR, SWIR, and the scene classification layer (SCL), which flags cloud, shadow, and cirrus. Water is NDWI > 0.1 with NIR ≤ 0.20 — the NIR cap rejects fresh snow, which would otherwise read as water. Ice is NDSI > 0.4 with NIR ≥ 0.11. Both indices are computed from reflectance, not raw digital numbers, which requires applying the scale and offset from the STAC metadata.
python
Python
# Baseline-aware DN → reflectancerefl = dn * scale + offset # offset = -0.1 post-04.00ndwi = (green - nir) / (green + nir + 1e-9)water_mask = (ndwi > 0.1) & (nir <= 0.20) & valid
The lake is identified as the water polygon containing a configured seed point — not the largest polygon, because a neighbouring lake is consistently larger.
The risk model
Every frame is evaluated using only data up to its own date. The model cannot look ahead. Four indicators feed the engine: lake area growth versus baseline, maximum shoreline advance beyond the baseline outline, a two-year Theil-Sen trend, and a drainage detector watching for two consecutive frames well below the running median. Levels are Watch, Advisory, Warning, Evacuate. Watch and Advisory require two consecutive evaluations before activating; Warning and Evacuate are immediate and never auto-cleared.
"The monitor reached Advisory two years before the flood. The Warning was post-event detection. That gap is the honest truth about what satellites can tell you without ground calibration."
On the real archive: Watch from October 2020, Advisory from October 2021, Warning on 24 October 2023 — the first clear scene post-outburst, driven by a 300+ m shoreline shift. The outburst reduced lake area by only about 14%, within the ~10% scene-to-scene noise, so drainage does not trigger from area alone.
The glacier layer
Raw NDSI per frame is useless for trend comparison: a snowy June scene looks like a year of glacier growth. The solution is a perennial ice composite using only end-of-ablation scenes (15 Sep – 31 Oct), classifying a pixel as ice only if it reads as ice in ≥70% of cloud-free observations that year. The 2018 composite is the fixed baseline; every subsequent year is compared against it, never the previous year, so loss accumulates visibly. Gain patches — almost certainly artefacts — are kept visible as a quality signal, not hidden.
The Randolph Glacier Inventory 7.0 provides an independent outline from around 2000, shown as a reference line only. The RGI includes debris-covered ice; the satellite composite does not. The difference is partly melt, partly method. Labelling matters.
The backend and frontend
Every day, AWS Lambda runs the ingest function: fetch the latest Sentinel-2 scene from RODA, compute NDWI and NDSI, build the water and ice outlines, evaluate risk, and dispatch an alert if a threshold is crossed. The processed archive — every observation back to 2018, serialised as JSON — is stored in S3. The code reads from that bucket on AWS, or from a local file when running offline; the application path is identical in both cases.
DynamoDB persists the alert audit log, pending operator approvals, and the demo SMS latch. Using a database instead of in-memory state means that a Lambda restart, a new ECS task deployment, or a container crash does not lose the record of what was already sent. The replay clock lives in a background thread on the server, not in the browser — alerts fire on schedule even with no browser open. That single design choice drives every subsequent infrastructure constraint.
React 19, MapLibre GL, Tailwind CSS v4. The shoreline morphs between real observations using linear interpolation, clearly labelled as such. Terrarium DEM tiles from AWS Open Data are extruded into a 3D terrain slab. Three views: Time Machine (the archive replay), Latest Scene (live computation), and Outburst Night (a scripted, hour-by-hour reconstruction of 4 October 2023, explicitly labelled as illustration).
What fought back
Clouds and the reflectance shift
At 5,000 metres the Himalayan monsoon, which runs June through September, overlaps nearly perfectly with the melt season. In a bad year there are three or four cloud-free scenes for the entire summer. The ablation window the glacier composite depends on often yields fewer than three scenes — a low-confidence flag in the UI. There was no clear scene for September 2023, the month before the outburst.
ESA's processing baseline 04.00 quietly added a −1000 DN offset to recent scenes without changing historical ones. Without correcting for it, extents from after 2022 are systematically wrong. The fix is one line of code, but the bug is subtle: the lake just looks marginally smaller than it should, and nothing throws an error.
The glacier tongue
High-altitude glaciers carry a debris-covered tongue whose spectral signature reads as bare rock, not ice. The composite shows the clean ice above the tongue; the lower glacier looks absent. The ice loss area the system reports is a lower bound. This is documented and labelled, but it is a real limitation.
Downstream impact data
The Teesta flood generated a large volume of reporting with figures that do not reconcile across sources. Death tolls differ between government bulletins; some include missing persons, some do not. The approach: store every reported figure with its source, date, and an official/media flag. Where sources disagree, both are kept. Nothing is averaged. Unverifiable figures are listed in a "could not verify" section rather than silently dropped.
Change detection along the flood corridor uses Sentinel-2 before/after composites; where monsoon cloud cover is too heavy, Sentinel-1 SAR from Microsoft Planetary Computer provides water-extent change without optical constraints. OpenStreetMap counts buildings and bridges in the change zone. They are labelled "structures in detected change zone," not "destroyed."
The SMS problem
In high-altitude Sikkim, mobile data is intermittent. SMS works when data does not. That is why SMS is the primary alert channel — not as a technical preference, but because an alert that requires a data connection does not reach the people most at risk.
AWS SNS delivers SMS to verified sandbox numbers cleanly. Reliable delivery to Indian numbers at scale is a different problem. TRAI's DLT framework requires a registered Principal Entity ID, a registered sender header, and a pre-approved template ID for every transactional message on local carrier routes. The message text must match the registered template exactly — an extra space, a case difference, a punctuation change, and the carrier silently drops it. DLT registration requires a formal organisation, not an individual, plus a separate AWS Support request for the sender ID. None of this is in Terraform; it is a separate checklist.
English and Hindi alerts go as separate SMS messages, English first, so if the Unicode message fails on a narrow-band link, the English one has already arrived.
The two-account architecture and demo safety
The SNS sandbox was on a different AWS account from the rest of the infrastructure. Rather than consolidate, the architecture formalises the separation. The SNS topic lives in a dedicated SMS account; the Lambda and ECS task role in the main account are granted
sns:Publish via the topic's resource policy. Cross-account publishing without cross-account credentials keeps the IAM blast radius small and auditable.Plain text
Main account (ap-south-1)Lambda (ingest) ──────────────────────┐ECS Fargate (desired_count=1) ────────┼──→ sns:Publish│SMS account (us-east-1) │SNS topic ←───────────────────────────┘├─→ SMS (sandbox: up to 10 verified numbers)
ECS runs with
desired_count = 1 and no autoscaling. The reason is in the Terraform comment: two tasks means two replay clocks, duplicate alerts, and a race condition on every threshold crossing. App Runner was ruled out because it throttles CPU between requests and the background thread must keep running. For the demo, a latch persisted to DynamoDB ensures the Outburst Night escalation to Evacuate fires its real SMS exactly once regardless of how many replays run. Every demo message carries a mandatory "DRILL - TEST ONLY:" prefix. The UI header shows the current delivery mode — simulated, live unregistered, or live DLT-registered — so there is no ambiguity about what is real.
What it shows, and what it does not
The satellite-only monitor reached Advisory two years before the flood. That is a meaningful signal. Converting it into a public warning still requires a human authority with ground knowledge and legal mandate. The system provides the signal; it cannot substitute for the institutional response. The thresholds are explicitly labelled as uncalibrated placeholders — calibrating them requires historical data from multiple events and collaboration with glaciologists and disaster-management authorities. That work has not been done.
What it does show is that the end-to-end path from a satellite observation to an SMS on someone's phone can be built on open data and open-source software. The pipeline is parameterised by lake; adding a new one is a configuration entry and a seed point. GLIMS estimates roughly 15,000 glacial lakes in the Hindu Kush-Himalaya region. South Lhonak is one of them.
The lake was growing for years. The data was there. Now, at least, there is a system that reads it.
Notes and data sources
- Sentinel-2 L2A: ESA Copernicus, via AWS Registry of Open Data (RODA), indexed by Element 84 Earth Search STAC. Coverage from December 2017.
- Randolph Glacier Inventory 7.0: RGI Consortium (2023). NSIDC/GLIMS. Source image dates vary around 2000.
- Risk levels: Watch October 2020; Advisory October 2021; Warning 24 October 2023 (post-event). Thresholds are uncalibrated placeholders.
- Terrarium DEM tiles: Mapzen, AWS Open Data. 3D terrain via MapLibre GL.
- India DLT: TRAI Telecom Commercial Communications Customer Preference Regulations, 2018 (amended 2020). Mandatory for transactional SMS on local Indian carrier routes.
- Human impact figures: curated from Sikkim government bulletins, NDMA advisories, ISRO/NRSC damage assessments. Conflicting figures retained separately; nothing estimated or averaged.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article