
I asked how much of Delhi’s groundwater is actually monitored. The answer was less than I expected.
I cleaned two messy government groundwater datasets, mapped where Delhi’s monitoring stations are, and built a small AWS tool (S3, Lambda and a Function URL) that shows where we have data, where we’re blind, and where the next stations should go.
I’m a chemical engineering student, and I started this hackathon wanting to build something about heat and water in Delhi. My first idea was a dashboard that ranked parts of the city by water stress. I even built it. Then I opened the real data, and I deleted it, because every number in that first version was a placeholder I had made up to see how it would look.
The real data asked a simpler question: how much of Delhi do groundwater monitoring stations actually cover?
The data was a mess
I downloaded Delhi’s groundwater telemetry from the National Water Data Portal. The first file had 173,132 readings across 96 stations. Roughly two thirds of the values were exactly zero, which is a sensor reporting nothing, not a water level. Others were 999, a common “missing” code. Some were as low as minus 847 metres. Some longitudes had lost their decimal point, so one station sat at 77,120,175 degrees east until I divided by a million and found it in West Delhi.
After filtering, about 11 percent of that file was usable.
A second file, from CGWB for 2026, looked cleaner, and mostly it was. But one value, 26.844, appeared 1,269 times from May onward across several stations. A real aquifer doesn’t report the same number to three decimals over and over, so I treated it as a stuck sensor and removed it. One station, Qatlupur_2, reported exactly 26.840 on every reading, and I dropped it too.
I ended up with 38 stations and sorted each into one of two tiers: reliable (24) or caution (14), the second meaning short records, flat readings, or suspicious repeated values. I kept the caution stations on the map and labelled them, because hiding uncertain data felt worse than showing it.
What the map says
I measured coverage as the share of Delhi’s area within 5 km of a station. With the nine stations I started with, reliable coverage was about 23 percent. Adding the 2026 stations raised it to about 57 percent. Everything else on the map is grey, which means no monitoring data.
The 5 km radius is my assumption, not a measurement, so I made it a slider. I also tested whether it was reasonable: for each reliable station, I checked how well its nearest neighbour predicted its depth. Within 5 km the typical difference was about 3 metres, and at 5 to 10 km it was about 7.5 metres, with a few pairs more than 15 metres apart. The trend isn’t statistically strong with only 24 stations, but the lesson is clear. “Covered” means a station is nearby, not that the spot is measured.
I also placed five hypothetical new stations, one at a time, each where it would cover the most uncovered area. Those five would lift reliable coverage to about 82 percent. They’re positions on a map, not checked sites, and I say so on the page.
A few more layers sit on top: 95 water-quality samples from a CGWB report (collected in May 2022, so not current), and the response of 18 stations to the 2026 monsoon. Twelve of them saw their water level rise afterwards. The three deepest-water stations didn’t recover, and I don’t know why. Groundwater was deepest in July and recovered by September, following a hot, dry April to June, but heat, missing rain and pumping all happen in the same months, so I can’t claim heat caused anything.
How it runs on AWS
The cleaned station file and the dashboard page sit in a private Amazon S3 bucket. A single AWS Lambda function written in Python does two jobs. If you open its URL with nothing added, it returns the dashboard page. If you add a latitude and longitude, it finds the nearest station and says how far away it is and whether the point is covered. A Lambda Function URL gives it a public address, so there is one endpoint for the page and the lookup. The function reads S3 with boto3, the open-source AWS SDK for Python, and its IAM role has read-only access to the bucket.
I had never used any of this before. Most of my time on AWS went on small errors, and they taught me more than the docs did. My first test failed with “NoSuchBucket” because my environment variable was called
Bucket and my code looked for BUCKET . Names are case-sensitive, and Lambda quietly ignored the one it didn’t recognise. Later the page showed a bare “Internal Server Error” in the browser. The real cause, “NoSuchKey”, only appeared when I ran the function from the Test tab: I had uploaded the page to S3 under a different filename. Both took minutes to fix once I could see the actual message, and hours to find without it.What I’d do differently, and what it can’t do
The Delhi boundary I used came from a third-party source whose date and licence I couldn’t verify, so the percentages are provisional. I believe the depth values are metres below ground, because water levels rose after the monsoon at most stations, but I haven’t confirmed that against CGWB documentation. Most stations have only one to two years of data, so I can’t say anything about long-term trends. And a gap on the map doesn’t mean there is no groundwater there, only that nobody is measuring it.
That’s the point, though. Before we argue about how much water Delhi has, we should know where we’re measuring. This map shows where we aren’t.
The code and data scripts are on GitHub: https://github.com/Anshika-017/Jaldrishti , and the live demo is at [ https://rkwrwlztdmr6ncc2by4pnmvan40wimio.lambda-url.ap-southeast-2.on.aws/ ].
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article