AWS Builder Center

MonsoonOps: Building a Serverless Rain-Readiness Ledger on AWS

Turning heavy-rain warnings into actionable building-level flood preparedness with AWS Lambda, API Gateway, DynamoDB, and S3. Lessons from building and debugging a serverless disaster-readiness prototype for South Asian residential communities.

MonsoonOps: Building a Serverless Rain-Readiness Ledger on AWS

From city-level weather warnings to building-specific action items: lessons about a weather-readiness application.

The situation: A weather alert is only the beginning

When heavy rains threaten cities like Bengaluru, Hyderabad, or Noida - a weather alert is an important signal. But to a building administrator, the information has limited value. What are the active concerns for their apartment complex? Has the basement pump been tested? Are the drainage grates clear? Is the secondary generator ready to power essential equipment? What vehicles should be moved out from the basement first? Who is responsible for the task, and how can the building confirm that the task is done?
A city-level alert is only a starting point for building-level preparedness. The gap between the two is the focus of our prototype, MonsoonOps.
MonsoonOps is a serverless rain-readiness ledger, intended for multi-unit residential buildings. The application's goal is to turn a rainfall trigger into specific, actionable tasks with evidence checkpoints.
We are particularly interested in evaluating the potential of cloud-based infrastructure to turn a general weather alert into a specific set of preparation instructions.
This article describes our prototype development, architecture decisions, and operational nuances around the application. At its core, MonsoonOps is concerned with two questions: what does it mean for a building to be prepared for heavy rains, and what does it take to implement such a preparation system effectively as a low-idle-cost, scalable application?

From a rainfall trigger to an action plan

MonsoonOps' application flow is centered around an incident, a rainfall trigger that requires building-level preparation. During such an incident, the application can list out a set of relevant tasks for administrators, security staff, maintenance workers, and residents, along with required evidence for critical actions and a vehicle-relocation prioritization list. For the purposes of a hackathon demo, we implemented a manual incident trigger, rather than an automated ingestion from a weather API.
The difference between the two approaches is significant: automated weather API ingestion and meteorological webhooks are a part of our production roadmap, but were not available for this prototype.
This is the most interesting aspect of our design. By design, MonsoonOps uses a set of AWS serverless components to implement a rainfall-incident management tool. This decision is driven largely by the expected operational profile of such an application: there is little to no need for background processing between rainfall events, and a burst of concurrent requests during an active incident.
As such, a traditional multi-server architecture would be a poor fit for the expected request volume patterns. Instead, we opted to use AWS Lambda as our primary application server.
We are particularly interested in exploring how rainfall-triggered applications can avoid high ongoing costs, and how the incidental request volume of a weather event can be harnessed to execute application logic.
The remainder of this article will examine the AWS architecture decisions that support this conclusion.

The AWS architecture

MonsoonOps uses the AWS serverless stack to implement the application logic, database, and evidence storage. The selected components are summarized below:
  1. AWS Amplify — frontend application hosting
  1. Amazon API Gateway — request routing and task execution
  1. AWS Lambda — primary application server
  1. Amazon DynamoDB — incident and task database
  1. Amazon S3 — private evidence storage
The application is configured to use the Mumbai Region ( ap-south-1 ) as its primary availability zone. The remainder of this section will examine the decisions that led us to these conclusions.

Designing the DynamoDB operations model

An important decision in designing the database model was to use a single-table architecture.
Our application makes extensive use of composite partition and sort keys to form a relational structure between related items. Below is a sample set of keys from the prototype application:
PK (partition key) SK (sort key) Description
 INCIDENT#2026-09   METADATA  General incident metadata, including trigger level and rainfall
 INCIDENT#2026-09   TASK#SEC_01  Security task, its status, and evidence reference
 INCIDENT#2026-09   VEHICLE#B2_104  Relocation assignment for a vehicle
 USER#SECURITY_01   ASSIGNMENTS  Security user's active tasks
These are sample keys from the prototype application, rather than production items. Using a relational model is useful for an application that needs to issue a set of action items for an incident, rather than individual user requests.
A single partition key can hold a group of related tasks, rather than spreading them across multiple tables. Similarly, vehicle assignments and user assignments can be queried using their respective partition and sort keys, rather than separate tables.
The main advantage of this approach is that any given item or group of items can be accessed using a single request to DynamoDB. This architecture is particularly well-suited to an application that only needs to query specific sets of related items.
DynamoDB's on-demand capacity mode is ideal for an application that has unpredictable request volume. We also make extensive use of conditional writes, particularly the  attribute_not_exists  variation, to prevent overwriting of task evidence.
Conditional writes are an important technique to prevent overwrites by multiple processes. However, they should always be applied to a specific attribute and item, rather than used at the database level.

The evidence verification workflow

A task such as verifying that a drainage grate is clear cannot always be completed by a simple checkbox. We designed the application to use an S3 presigned URL evidence verification workflow.
There are three main steps to the process:
  1. Evidence request: the frontend requests a presigned URL for an S3 object
  1. Evidence submission: the browser makes a direct request to the S3 bucket
  1. Evidence verification: the application verifies the existence of the S3 object
Each step has advantages and drawbacks. First, the frontend makes an API request to get a URL that is valid for five minutes from the current time. This presents a limited window for submitting the photograph, but it is a necessary security measure to prevent tampering.
Using a short expiration is particularly important for applications that accept user-submitted content. The next step, evidence submission, has its own complications.
Once the frontend receives a presigned URL, it makes a direct request to the S3 bucket. This means that the image request does not go through API Gateway or Lambda, reducing the overall request latency.
Making this a direct browser-to-S3 request also reduces application processing: there is no need for an additional image handler in the application backend. With that said, the current implementation does not verify that the image is relevant to the submitted task or contains any specific content.
After the user submits the task for completion, the Lambda function makes a request to  head_object  and verifies that the file exists in the bucket and has the expected size. Finally, the task status is updated in DynamoDB. With that said, there are several security considerations to this implementation.
The  head_object  request only confirms that an object with the given key exists in the bucket. It does not confirm that the image was submitted by the current user, nor does it confirm that the image was submitted with the correct metadata.
A production-ready application would also need additional security and authorization checks, such as restricting object access to specific IAM roles. Additionally, individual task submissions might require object-level verification and content filtering.
The current implementation does not account for these possibilities. We treat the evidence as a proof of submission, rather than a proof of content. As such, we only make basic existence and size checks.
AI-based image verification and EXIF-based location tagging would be useful additions to a production application. With that said, this is outside the scope of a prototype application.

Three engineering problems we encountered

This section will discuss three engineering challenges that we encountered while developing the application.

1. Browser CORS failures despite successful API tests

One of the first issues we encountered was that while our API tests were successful, the browser was raising CORS errors.
The underlying cause for this issue was that the browser makes an OPTIONS request prior to making the actual request. This is a preflight request that determines whether the actual request is safe to make.
In the case of our API Gateway setup, there was no route handler for the OPTIONS method. This meant that the OPTIONS request was failing, and the actual request was blocked by the browser.
The solution to this issue was to update the Lambda router to handle the OPTIONS method and provide the appropriate response headers. This was an unexpected issue to encounter, but it highlights the importance of ensuring that the API Gateway is properly configured.
CORS headers should only be set if the actual request is expected to arrive at the backend. With that said, any production application should also restrict the allowed origins and methods to avoid unexpected issues.
If the application is only expected to be used by a single origin, it should explicitly whitelist the expected origins and methods.

2. S3 presigned uploads and regional endpoints

We encountered an issue where the S3 presigned URL was attempting to use an endpoint in a different region than the bucket was in.
While this is not a significant issue for most applications, it became a complication for us, as we were using a browser-based PUT request to submit the image.
The browser was following the redirect, which resulted in an unexpected HTTP 307 Temporary Redirect response. Instead of following the redirect, we updated the Python S3 client to use the Mumbai regional endpoint.
This change also uses virtual-hosted–style Amazon S3 URLs, rather than the default path-style URLs. We also set the  signature_version  to  v4 .

3. Cross-platform deployment packaging

One of the final issues we encountered was that the deployment package was not being created correctly on Windows. Specifically, the ZIP archive was using backslash separators rather than forward slashes.
While this is a minor issue, it resulted in an error when the application attempted to load the module. We resolved this issue by writing a custom Python script to create the deployment ZIP archive.
This was an important reminder that while the application code may be correct, the deployment package can still contain issues.

What serverless changes about the cost model

One of the most interesting aspects of this architecture is that the backend does not need to be running at all times. Lambda functions only execute when they are invoked, and DynamoDB only incurs costs when it is being accessed. S3 is used for evidence storage, and it does not incur any costs unless it is being accessed.
Amplify hosts the frontend application, while the API Gateway exposes the application's HTTP interface.
As such, this architecture is ideal for an application that does not have a large number of concurrent users. For a prototype application, this is an acceptable choice.
This architecture also has a zero-idle-cost production profile, which is advantageous for applications that do not need to be running at all times.
With that said, it is important to understand the difference between an application that has no idle cost and an application that has zero cost.
While the Lambda and DynamoDB components do not incur costs when they are idle, other components such as API Gateway, S3, Amplify, and the application server can still incur costs. In a production scenario, it is important to ensure that the application does not have any unnecessary costs.
This difference is particularly important for applications that operate on a shoestring budget.

What we built and what comes next

The current MonsoonOps hackathon demonstration is capable of simulating a rainfall incident trigger, role simulation, incident and task workflow, vehicle-relocation assignment, and S3 evidence uploads and verification. As discussed in this article, our proposed production architecture has five major components: automated weather ingestion, identity and access management, evidence verification, event-based notifications, and concurrency controls.
Each of these components would need to be implemented, tested, and operationalized prior to production deployment.
For a production-level deployment, it would also be important to consider the implications of failure, permissions, auditing, and evidence retention, as well as the impact of incorrect or delayed task assignment.

Final thoughts

Developing MonsoonOps has been an enlightening experience for us: it reinforced our understanding of what constitutes a useful cloud-based application.
Lambda provided the event-driven application backend, DynamoDB provided the operational ledger, S3 provided the document storage, and API Gateway and Amplify provided the necessary infrastructure to make it all come together.
More importantly, it made us think through the details that are often overlooked in an architectural diagram, such as CORS headers and regional endpoints.
MonsoonOps is a hackathon prototype, but it represents a viable approach to developing a low-idle-cost, building-level rain-readiness application. We believe that the principles that we applied can be useful in other contexts as well.
Weather alerts are only useful if they result in building-level preparedness. MonsoonOps is our prototype application that attempts to address this issue.


Project links
Built as a student project for Environmental Hacks 2026 — Bharat Builds Tour.
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