AWS Builder Center
From "Do I need rainwater harvesting?" to a monsoon-checked system, serverless on AWS.

From "Do I need rainwater harvesting?" to a monsoon-checked system, serverless on AWS.

How we turned Delhi's rainwater rules, ten years of real rainfall and a photo of a dirty filter into one plan a homeowner can act on, built with AWS Lambda, Amazon Bedrock, Amazon Location Service and DynamoDB.

A 120 m² roof in Lodhi Road

Take one ordinary house in central Delhi: a 120 m² concrete roof on a 150 m² plot, four people, and a water bill of ₹900 a month.
In an average year about 72,000 litres of rain land on that roof and run off it, which is roughly seven water tankers. Most of it goes into the street drain. Because the plot is over 100 m², Delhi's rules say this house must have a rainwater harvesting system. If it doesn't, the Delhi Jal Board can add a penalty to the water bill. If it does, the owner can get financial help to build one and a rebate on the bill every year.
When we asked homeowners about it, almost none could answer the first questions:
  • Is it mandatory for my house?
  • What should I build, and how big?
  • What will it cost me after the subsidy?
  • How do I apply?
  • How do I know it still works next July?
The last question matters most. Surveys of cities that made harvesting mandatory found that a large share of the systems people built stopped working. Around 55% were reported non-functional in Bengaluru and 70–80% defunct in Faridabad. A pit full of silt or a filter blocked by leaves looks the same from the street as one that works.
Boond (बूँद, "drop") is our answer. A homeowner or RWA secretary types an address, outlines the roof on a map, answers four questions, and in about 30 seconds gets:
  • whether harvesting is mandatory for them;
  • the structure to build and its exact size;
  • the cost after assistance and the payback period;
  • a pre-filled application PDF.
After the build, a phone photo of the filter or pit is checked by a vision model before every monsoon, with an email reminder when it's due.



The problem is follow-through, not information

The rules are public and the engineering is standard, yet harvesting fails at three points: deciding what to build, filling in the application, and keeping the system working once nobody checks it.
So Boond doesn't stop at one answer. It follows each plan through its whole life:
Plain text
planned → applied → installed → verified ⇄ needs_attention



Architecture: one journey, ten Lambda functions

Boond is fully serverless and defined in one AWS SAM template. The React + Vite frontend uses Leaflet and Geoman to draw the roof and  @turf/area  to measure it. It's hosted on AWS Amplify and calls an API Gateway HTTP API, backed by ten Python 3.12 Lambda functions on arm64:
Step
Lambda
AWS services and data
Find the house
Geocode
Amazon Location Service (Esri), Nominatim fallback
Get the plan
Plans
Open-Meteo rainfall archive, DynamoDB
Read the rules
Rules
delhi_rules.json, structures.json
Ask "what if…?"
Agent
Amazon Bedrock (Nova Lite) via Strands Agents SDK
Apply
Application
reportlab PDF → S3, presigned link
Officer review
Review
OpenStreetMap Overpass, DynamoDB cache
Photo check
Maintenance
S3 presigned upload → Bedrock Converse vision
Remind
Reminders
EventBridge Scheduler → SNS email
Ward view
Wards, Dashboard
Overture footprints, DynamoDB GSI

Splitting the work into one function per job gives each its own IAM role: only Agent and Maintenance can call Bedrock. It also lets each function have its own timeout. The Agent gets 1 GB and 29 s, and Reminders gets 120 s. All state lives in one DynamoDB table: a plan, its photo checks and its chat share one partition key, and a ward/status GSI powers the dashboard.



The calculations

Every number below comes from two JSON config files, not from code.

1. Rain on this roof

Plain text
key = RAIN#<lat, lon rounded to 2 dp> (≈ 1 km cell)
cache hit → use it
else → Open-Meteo: daily rainfall for the last 10 full years
annual_mm = average of the 10 yearly totals; cache the annual figure AND the daily series
failure → 750 mm Delhi default, labelled "default"

2. Runoff, tankers, compliance

One millimetre of rain on one square metre of roof is one litre.
Plain text
litres_per_year = roof_m2 × annual_mm × coefficient (RCC 0.80 · tin 0.85 · tiles 0.75)
tankers = litres_per_year ÷ 10,000
mandatory = plot_m2 ≥ 100 (the plot, not the roof)

3. What to build, and how big

A structure overflows during a heavy burst, so it's sized for one design storm rather than the whole year: 60 mm/h for 15 minutes.
Plain text
storm_litres = roof_m2 × 15 mm × coefficient

Open ground AND recharge safe here?
├─ yes → roof ≤ 300 m² → RECHARGE PIT 3 m deep; side = √(storm_m3 ÷ 3), rounded UP to 0.1 m, kept within 1–2 m; ₹3,500/m³
│ roof > 300 m² → RECHARGE TRENCH 1 m × 1.5 m; length = storm_m3 ÷ 1.5, rounded UP to 0.5 m (min 2 m); ₹3,000/m³
└─ no → STORAGE TANK smallest of 1k/2k/3k/5k/10k L ≥ max(storm_litres, people × 20 L × 3 days)
+ first-flush filter, ₹8,000, on every system
"Recharge safe" comes from three questions:
  • Is there a septic tank, soak pit or sewer line nearby?
  • Does the street waterlog?
  • Is the only open ground next to the foundation?
Any yes switches the plan to a tank, because pushing water into the ground there risks contaminating groundwater or damaging the building. Not sure keeps the pit but adds a warning. We cite no setback distances because we couldn't verify an official figure.
Roof
Storm
Structure
Size
Install cost
120 m²
1,440 L
Pit
1.0 × 1.0 × 3.0 m (0.69 m → min 1.0)
₹18,500
300 m²
3,600 L
Pit
1.1 × 1.1 × 3.0 m (1.095 → 1.1)
₹20,705
400 m²
4,800 L
Trench
3.5 × 1.0 × 1.5 m (3.2 → 3.5)
₹23,750
1,500 m²
18,000 L
Trench
12.0 × 1.0 × 1.5 m
₹62,000

4. The money

Plain text
assistance = min(₹50,000, 50% × install cost)
you pay = install cost − assistance
rebate = bill × 12 × 10% per year
penalty avoided = bill × 12 × 50% per year, only if mandatory
tanker savings = tankers bought × ₹4,500 per year
tank water = litres used ÷ 1000 × ₹50/kL (tanks only)
payback = you pay ÷ yearly benefit ("no payback" if 0)

The worked example

Step
Calculation
Result
Rainfall
Open-Meteo 10-year average
752.1 mm
Water a year
120 × 752.1 × 0.8
72,202 L (7.2 tankers)
Mandatory?
150 ≥ 100
Yes
Design storm
120 × 15 × 0.8
1,440 L
Pit
√(1.44 ÷ 3) = 0.69 → min 1.0
1.0 × 1.0 × 3.0 m, 3,000 L
Install
3 m³ × ₹3,500 + ₹8,000
₹18,500
Assistance
min(50,000, 9,250)
₹9,250
You pay

₹9,250
Benefit
₹1,080 rebate + ₹5,400 penalty avoided
₹6,480/yr
Payback
9,250 ÷ 6,480
1.4 years
If the same house has no open ground, it gets a 2,000 L tank: ₹24,000 to install, ₹12,000 to pay, and a 1.9-year payback.

5. The number that looked right but wasn't

Our first version said "72,202 litres saved a year". That's how much rain falls, not how much a system keeps. Delhi's rain arrives in a few heavy monsoon days, a tank holds only so much, and a pit soaks only so much in a day. So Boond now replays ten years of real daily rainfall through the recommended structure:
Plain text
each day: inflow = mm × roof × coefficient
pit/trench: kept = min(inflow, capacity × 3) # drains and refills ~3× a day (labelled assumption)
tank: fill up to capacity, overflow the rest; household draws people × 20 L a day
The replay showed two things:
  • A pit almost never overflows. At Lodhi Road it takes 9,000 L a day, which is only exceeded on a day above 93.75 mm. On 31 July 2024, 116 mm fell. The roof produced 11,136 L, the pit kept 9,000 L, and 2,136 L overflowed. That was one day in years.
  • A tank keeps far less than the headline. Four people drawing 80 L a day can use at most 29,200 L a year, under 40% of what falls on the roof, and less in practice. One 50 mm day sends 4,800 L at a 2,000 L tank, and 2,800 L overflows at once.
So Boond recommends recharge first wherever it's safe, and values tank water only at what the household actually uses.



Rules belong in config, not in code

Delhi's rules have changed several times since 2001. If the ₹50,000 cap were hard-coded in Python, every rule change would mean a redeploy. Instead the calculator is made of pure functions, and every threshold, fraction, price, coefficient and assumption lives in  delhi_rules.json  or  structures.json .
Each policy value records its source, URL and the date we checked it (7 October 2026). The file also states that the DJB's own PDFs weren't reachable at the time. Moving Boond to another city means writing a new rules file, not a new app.



An agent that can only touch one plan

Homeowners ask questions like "what if I only have a small backyard?" or "सब्सिडी कितनी मिलेगी?" ("how much subsidy will I get?"). The assistant runs Amazon Nova Lite on Bedrock through the Strands Agents SDK.
It never sees a plan ID or a database client. Its six tools are closures created for one plan:
  •  get_plan ,  explain_rules  and  maintenance_tips  only read data.
  •  recalculate  previews a change without saving it.
  •  save_plan_changes  and  generate_application  run only after the user says yes.
The system prompt sets five rules:
  • State only numbers that come from a tool.
  • Act first: call  recalculate  instead of asking clarifying questions.
  • Ask before saving anything.
  • Reply in the user's language.
  • Always say to confirm subsidy, rebate and penalty with the Delhi Jal Board.
What fought back: Nova Lite sometimes sent  "openSpace": "true"  as a string. Strict validation rejected it, and the agent got stuck apologising in a loop. Typed tool parameters plus a small coercion step fixed it. If Bedrock is unavailable, the Lambda returns a friendly 503 and doesn't save the question.



The photo check: a vision model with a strict contract

Before each monsoon, a daily EventBridge Scheduler rule wakes the Reminders Lambda. It emails, through SNS, every installed system that's due for a check.
The homeowner's photo is downscaled in the browser to a 1,600 px JPEG at quality 0.85. It's uploaded straight to S3 through a 15-minute presigned URL, then sent to Bedrock Converse at temperature 0 with a prompt that asks for one JSON object only:
json
JSON
{"component": "filter", "verdict": "needs_cleaning",
"reason": "Dry leaves are covering the filter mesh.", "confidence": 0.85}
The parser assumes the model can be wrong. It extracts the first  {…} , checks the verdict against four allowed values and clamps the confidence. If the reply is unusable, it retries once, then returns  unclear .
Plain text
unclear OR confidence < 0.6 → "please retake" (nothing changes)
healthy AND taken at the house → verified
needs_cleaning / broken → needs_attention + a specific fix tip
"Taken at the house" means within 150 m of it, plus up to 100 m of GPS uncertainty, using browser location or EXIF GPS. The photo must also be less than 15 minutes old. That stops anyone verifying a system with a photo from the internet.
In testing, a clogged gutter came back  needs_cleaning  (0.9) and a restaurant photo  unclear . A verified system earns a "Boond Verified" certificate with a QR code that links to its live status.
For installed systems, Boond also replays real daily rain since installation. It counts nothing on the days between a failed check and the next healthy one. A missed cleaning shows up as litres lost this monsoon.



From one roof to a whole ward: the ward officer’s view

Boond’s second user is the ward officer, the Jal Board or municipal official responsible for rainwater harvesting in one ward. Today that job is mostly paper: forms, site visits, and no way to say how many required buildings actually harvest. Boond gives them two screens.
1. The application queue. Every filed application lands in that ward’s queue, newest first. The officer sees the roof outline, plot, residents, recommended structure, any site-safety flags, the cost after assistance and the PDF.
What a form never shows is where the water will go. So Boond pulls real ponds and lakes within 2 km and drains within 600 m from OpenStreetMap Overpass (cached per ~100 m cell for a week) and suggests a destination: recharge on site if safe, else the nearest pond, else the storm drain, else storage and reuse.
The officer picks the destination on the map and records approved, site visit needed or rejected. The last two require a note. The decision appears on the homeowner’s plan straight away and is kept in its review history.
2. The ward dashboard and “simulate monsoon.” This answers *how much of this ward’s rain are we actually catching?*Boond loads Overture Maps building footprints for five Delhi wards, colours each roof by the litres it could harvest, marks it required if the footprint is at least 100 m², and overlays every Boond plan by status.
The officer then picks any past date, and Boond replays that day’s real rain over every roof:
  • Installed or verified systems keep up to capacity × 3; the rest overflows.
  • Systems flagged “needs attention” lose all their runoff, because a broken system catches nothing.
  • Unbuilt or unplanned buildings send all their runoff to the drains.
On 31 July 2024 that meant 116 mm at Lodhi Road and about 280 mm over parts of east Delhi. The screen shows litres kept today beside litres kept if every required building harvested. The gap is the officer’s enforcement case for one real storm, and it shows where to act first: broken systems, and large required roofs with no plan.


Every Delhi roof already collects rainwater, and most of it goes into the drain. Boond tells each house what to build, gets the application filed, and checks every monsoon that the system still works.
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