Building JalRakshak: A Serverless Flood Early Warning System with AWS Lambda, DynamoDB and SNS (Tested on LocalStack)
How I built a crowd-sourced flood alert system with Lambda, DynamoDB and SNS, and tested it on LocalStack without a billing-enabled AWS account.
The problem
Every monsoon, underpasses and roads in Indian cities like Delhi flood within minutes. Commuters usually find out only when they are already stuck, while municipal drainage teams learn about the worst spots late. I wanted to build something simple: let citizens report a flooded road, show it on a live map, and alert civic teams when it is severe.
That became JalRakshak, a hyperlocal flood and waterlogging early warning system.
What it does
- Citizens report a flooded road with its name, water depth and severity.
- The backend scores the risk and stores the incident.
- A live map and table show all hotspots, colour-coded by severity.
- For severe reports, an alert is published so municipal teams can dispatch pumps faster.
- A safe-route finder suggests a path that avoids flooded points.
Architecture
The flow is:
Browser dashboard (HTML + Leaflet) -> API -> AWS Lambda handler -> Amazon DynamoDB + Amazon SNS (+ Amazon S3 provisioned)
- AWS Lambda: one handler (
lambda_handler.py) servesPOST /reportandGET /hotspots.
- Amazon DynamoDB: table
JalRakshakIncidentskeyed byincidentId, with a Global Secondary Index onseverity.
- Amazon SNS: a topic receives an alert whenever a severe report comes in.
- Amazon S3: a bucket is provisioned for geo-tagged flood photos (the upload feature is not built yet).
- AWS SAM:
template.yamldefines all of the above as infrastructure as code.
The roadblock: no billing-enabled AWS account
I had an AWS account but no payment method on it, so I could not deploy to real AWS. Instead of giving up, I used LocalStack, an open-source AWS emulator that runs in Docker. The hackathon allowed building with AWS open source tools, which made this a valid route.
Starting LocalStack was one command:
Plain text
docker run -d --name localstack-main -p 4566:4566 localstack/localstack:3.8.1
I pinned the version to 3.8.1 because newer LocalStack releases may need an auth token.
Making the code work on both LocalStack and real AWS
The trick is a single environment variable. In the Lambda handler, boto3 clients take an optional
endpoint_url :Python
ENDPOINT = os.environ.get("AWS_ENDPOINT_URL")dynamodb = boto3.resource("dynamodb", endpoint_url=ENDPOINT, region_name=REGION)sns = boto3.client("sns", endpoint_url=ENDPOINT, region_name=REGION)
On my laptop,
AWS_ENDPOINT_URL points to the LocalStack container on port 4566. On real AWS it is not set, so the exact same code talks to the real services.A small Flask server (
local_server.py ) stands in for API Gateway. It receives the browser request and calls the same handler() function, passing an API Gateway style event.What I learned (and what broke)
- My first Lambda was fake. The early version returned hardcoded data and never imported boto3. Once I rewired it to read and write DynamoDB, the demo became real.
- DynamoDB returns numbers as
Decimal.json.dumpsfails on them, so I added a small converter before returning the response.
- Resource names must match the SAM template. My first LocalStack setup used guessed names and the handler could not find the table. Matching names to
template.yamlfixed it.
- PowerShell eats JSON quotes. Testing the API with
curl.exefailed because of quoting, andInvoke-RestMethodwith a single-quoted body worked.
- Be honest about what is simulated. My dashboard first claimed Amazon Bedrock and live radar data. I relabelled them as demo, because they were not real.
What is real and what is not
Real (running on LocalStack): Lambda handler logic, DynamoDB storage, SNS publishing.
Simulated: the AI copilot replies and the rainfall card use sample data.
Planned: Amazon Bedrock for the copilot, and S3 photo upload with image-based depth estimation.
Try it yourself
Requirements are Docker Desktop and Python 3.10+.
Plain text
docker run -d --name localstack-main -p 4566:4566 localstack/localstack:3.8.1python -m pip install boto3 flask flask-corspython setup_localstack.pypython local_server.pypython -m http.server 8080
Then open port 8080 on localhost in your browser. The same
lambda_handler.py and template.yaml are meant to be deployed to real AWS with sam deploy .Final thoughts
Not having a billing-enabled account turned out to teach me more about how AWS services fit together than a one-click deploy would have. If you are a student or solo builder in the same position, LocalStack plus SAM is a solid way to build and test a serverless backend before you ever touch a bill.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article