AWS Builder Center
Aahat: watching Himalayan glacial lakes from space, and warning the villages below in Hindi

Aahat: watching Himalayan glacial lakes from space, and warning the villages below in Hindi

How I built a flood early-warning system for Himachal Pradesh on Sentinel-2 open data, EC2, S3, Polly and SNS in three days, what broke along the way.

A phone buzzes in a village called Thirot. The screen is red and says the water is about 106 minutes away. A glacial lake 64 km up the valley has just burst.
That's a simulation. But the lake is real, the village is real, and the number comes from real data. This post is about how I built the thing that produces it, for the WeMakeDevs × AWS Environmental Hacks hackathon (Heat and Water track).

The problem

As glaciers melt, they leave lakes behind, often held back by nothing more than loose rock. When one of these gives way, the flood runs down a valley where people live right beside the river. It's called a glacial lake outburst flood, and the people downstream usually find out when the water arrives.
I wanted to answer one question for someone living in that valley: is there a lake above me, would its flood reach me, and how long would I have?

What Aahat does

Aahat (आहट) watches 22 glacial lakes in and around Himachal Pradesh.
  • It measures each lake from Sentinel-2 satellite images, every season since 2017. Gepang Gath, for example, has grown 26% in nine years.
  • It gives each lake a risk score that shows its working: size, growth, the slope at the outlet, the ice and rock that could fall in. Each factor names the published study behind it.
  • It traces where a flood would go and estimates how many minutes it would take to reach each village, bridge and road on the way.
  • A villager types their village, or asks out loud in Hindi, and gets a plain answer.
  • An official gets a dashboard, a flag when heavy rain or a heat spike is forecast, and one button that warns the villages below, nearest first, each with its own countdown.

How it's built on AWS

The whole thing starts with the Registry of Open Data on AWS. Sentinel-2 imagery and the Copernicus elevation model are both there as cloud-optimised files, which means my pipeline can read just the few hundred pixels around a lake instead of downloading a whole scene. That one property is what made this possible on a student budget.
  • Amazon EC2: one small instance in Mumbai. A timer runs the Python pipeline every two days to pick up new satellite passes. The same box runs the Go API and serves both web apps.
  • Amazon S3: the pipeline publishes its results to a bucket, and the API serves from it. The data folder is public, so anyone can download the outlines, scores and flood paths.
  • Amazon Polly: speaks every warning and every answer in Hindi. A voice reaches people that text doesn't.
  • Amazon SNS: sends the alert texts, and emails me when a job on the server fails.
  • AWS SDK for Go v2 and the AWS CLI: the API talks to S3, Polly and SNS through the SDK, and every piece of infrastructure is created by CLI scripts in the repo.

What broke, and what I learned

This is the part I'd have wanted to read before starting.
The satellite's own cloud mask lied about dark lakes. Deep, clear glacial lakes kept getting labelled as "cloud shadow" and thrown away. I had to treat those labels as "not sure" instead of "not water".
One scene is not enough for a tiny lake. My sudden-drainage check flagged a lake as 73% emptied. It hadn't. The lake is a couple of hundred pixels, and at that size one image differs from the season average by tens of percent. Every large lake stayed within 1% on the same check, so now small lakes are simply not checked that way.
Two numbers disagreed, and the assistant repeated both. For one village, the data said "flooded" and also "ground 4.1 m above the flood". The Hindi assistant faithfully told the villager both. The cause was two code paths using two different water levels. Now one level decides both, and a test fails if they ever disagree again.
An AI that answers about floods must not invent numbers. The assistant can only use figures it looked up from our own API, and every number in its answer is checked against that lookup before it's shown. If the check fails twice, the villager gets a fixed template built from the data instead.

Being honest about it

I compared my flood estimates against studies of two of these lakes by NRSC, part of India's space agency. On peak flow, their numbers fall between my two scenarios at all five benchmark sites. On flood depth, at three of five. The table is in the README, disagreements included.
So, plainly: these are screening estimates from a 30 m elevation model, not a hydraulic model. Aahat can't see a burst as it happens and can't predict when one will. Nobody in Lahaul has used it yet. Text messages only reach verified numbers because my account is still in the SNS sandbox, and I had planned to run the assistant on Amazon Bedrock but model access wasn't enabled on my new account in time, so it runs on Claude through Anthropic's API with the Bedrock path ready in the code.

What's next

  • A statewide inventory. Himachal has far more glacial lakes than the 22 I watch.
  • Getting it in front of people who actually live below these lakes, and the officials responsible for them.
  • Real SMS and voice delivery, and river sensors feeding the webhook that already exists.

Try it

I built this in three days with Claude as my coding partner. If you work on floods, glaciers or disaster response in the Himalayas, I'd love to hear what I got wrong.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article