
Tankwise: Building a Rain-Aware Water Planning Tool with AWS Serverless
How I built a water-tanker planning prototype using React, rainfall forecasts, AWS Lambda, Amazon API Gateway, and DynamoDB. This project explores how a simple, explainable water-balance model can help residential buildings make better-informed water procurement decisions.
Tankwise: Building a Rain-Aware Water Planning Tool with AWS Serverless
The problem: Ordering water at the right time
For hostels, paying guest accommodations, and residential buildings, managing water supply involves a practical question: When should the next water tanker be ordered?
Order too early, and the building may pay for water before it needs it. Order too late, and the available supply could fall below the required reserve before the tanker arrives.
Rain adds another variable. If a building has a rooftop rainwater collection system, rainfall may temporarily extend the time before a tanker is needed. However, rainfall is uncertain, and relying entirely on a forecast can be risky.
I built Tankwise to explore this problem through an explainable, rain-aware water-planning application.
The aim was not to build another generic AI dashboard. Instead, I wanted to turn a real operational decision into a transparent calculation, expose its assumptions, and use AWS to handle the backend processing and persistence.
Designing a practical solution
Tankwise takes a building's current water stock, tank capacity, estimated daily consumption, roof area, rainwater collection efficiency, supplier lead time, and safety-stock requirement.
It combines these inputs with a daily precipitation forecast from Open-Meteo and produces three important outputs:
- The latest calculated safe day to book the next tanker under the forecast scenario.
- A separate booking window assuming no rainfall.
- An estimated top-up quantity based on the projected stock when the tanker arrives.
Keeping the no-rain scenario visible is deliberate. A weather forecast is an estimate, not a guarantee, so the application should not hide the risk of planning around expected rainfall.
Tankwise is a decision-support prototype. It does not automatically order tankers, guarantee that water will be available, or claim measured water or cost savings.
Architecture: React, Lambda, API Gateway, and DynamoDB
I chose a serverless architecture to keep the backend relatively small and avoid managing a dedicated application server.
The main components are:
React and Vite — Frontend
The frontend provides the input controls, water-balance results, forecast and no-rain comparison, and saved-decision history. Open-Meteo supplies the daily precipitation forecast.
Amazon API Gateway — HTTP API
API Gateway exposes four routes:
-
GET /health
-
POST /simulate
-
POST /records
-
GET /history
These routes provide a clear boundary between the user interface and the backend.
AWS Lambda — Calculation and request processing
A Python 3.12 Lambda function validates requests, runs the water-balance model, and handles API operations.
An important design decision is that saving a record does not blindly trust a calculation supplied by the browser. The Lambda recalculates the result from the validated inputs before persisting it.
Amazon DynamoDB — Decision history
DynamoDB stores the inputs and calculated outputs associated with saved plans. The table uses
building_id as its partition key and sort_key as its sort key, allowing records for a building to be retrieved in reverse chronological order.AWS SAM and CloudFormation — Infrastructure
I used AWS Serverless Application Model (SAM) to define and deploy the API, Lambda function, DynamoDB table, permissions, and logging resources through infrastructure as code.
CloudWatch Logs provides a place to investigate backend failures.
Making the water calculation explainable
Tankwise does not need a machine-learning model to answer its core question. A deterministic model is more appropriate when the underlying quantities and assumptions can be explicitly represented.
The rainwater captured by a roof is estimated using:
\text{Rainfall (mm)}
\times
\text{Roof area (m²)}
\times
\text{Collection efficiency}
]
This follows from the useful physical relationship that one millimetre of rain over one square metre represents one litre of water before collection losses.
The model then simulates each day in sequence:
- Subtract daily water demand.
- Add estimated captured rainwater.
- Limit the resulting stock to the tank's capacity.
- Track overflow and unmet demand separately.
The booking calculation incorporates supplier lead time and a safety-stock threshold. Tankwise runs the calculation under both the rainfall forecast and a zero-rain scenario, making the difference between the two outcomes visible.
The forecast horizon is 14 days. Beyond the loaded forecast, the model assumes zero rainfall rather than inventing future weather values.
This approach has limitations. Estimated daily demand may not reflect peak consumption, roof measurements may be inaccurate, collection efficiency varies, and actual tanker delivery times can change. The recommendation is only as reliable as the inputs and assumptions.
Keeping the frontend and backend consistent
The project maintains the model in two forms: JavaScript for browser-side calculations and Python for backend calculations.
Duplicating business logic can create subtle inconsistencies. A formula may be updated in one language but not the other, or the two versions may behave differently on invalid inputs.
To reduce this risk, I added a parity-check script that runs the two implementations against the same inputs and compares their outputs and error messages.
The validation suite covers edge cases such as empty forecasts, stock below the safety reserve, rainfall overflow, zero supplier lead time, excessive forecast length, and days eight through fourteen.
The latest recorded local checks passed:
- 32 frontend tests.
- 37 backend tests.
- 2,027 JavaScript/Python parity scenarios.
- The SAM template validation and local build.
These results establish consistency across the tested scenarios; they do not prove that every real-world situation is handled correctly.
Deployment and integration lessons
I deployed the backend using AWS SAM in the Asia Pacific (Mumbai) region (
ap-south-1 ). This provisioned the HTTP API, Lambda function, DynamoDB table, and supporting resources.The frontend and backend have different deployment responsibilities. SAM deploys the backend infrastructure, while the React application must be built and hosted separately. The frontend's
VITE_API_BASE_URL setting points it to the deployed API.This separation also means that a successful backend deployment does not, by itself, prove that the entire application works. The frontend must be configured with the correct endpoint, the browser must be able to make requests, and the API's CORS headers must agree with the actual hosting origin.
I encountered this distinction while working on frontend hosting: a successful Amplify deployment status did not guarantee that the website would serve the application's
index.html . Diagnosing the hosting configuration separately from the backend helped clarify where the failure occurred.That is an important lesson for small serverless projects: validate each layer independently, then verify the complete user journey.
Security and operational limitations
Tankwise is still a hackathon prototype, not a production-ready water-management service.
The current API has no authentication, and its write and history endpoints are publicly reachable. CORS configuration can restrict which browser origins are allowed to read responses, but it does not prevent direct API calls from scripts or other clients.
Before real use, I would add appropriate authentication and authorization, enforce building-level access controls, introduce appropriate usage limits and cost alerts, and establish a data-retention policy. I would also configure DynamoDB point-in-time recovery and retention safeguards.
The application should use non-sensitive demonstration data until these protections are in place.
Rainwater collection should not be interpreted as making water safe to drink. Tankwise estimates water quantity, not water quality.
What I learned
The central lesson from Tankwise is that useful engineering is not necessarily about choosing the most complicated technology.
A transparent calculation, carefully chosen inputs, explicit uncertainty, and a reliable record of previous decisions can provide more value than adding AI without a clear need.
AWS services support the application in distinct ways: API Gateway exposes the interface, Lambda executes the backend logic, DynamoDB preserves decisions, and SAM makes the infrastructure reproducible. Each component has a clear responsibility.
The remaining work is to complete and verify the public frontend deployment, validate the full workflow against the deployed AWS backend, and improve access control and operational safeguards.
Conclusion
Tankwise began with a simple question: how long can a building safely wait before ordering more water?
By combining rainfall estimates with a deterministic water-balance model and a serverless AWS backend, the project turns that question into a decision that users can inspect rather than blindly trust.
For me, the value of this prototype is the engineering process behind it: taking a concrete problem, making assumptions explicit, testing the model across two implementations, deploying the backend through infrastructure as code, and being honest about the limitations that remain.
The next milestone is not adding more services. It is proving that the complete application works reliably from forecast retrieval through decision persistence, while making it safer for real users.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article