AWS Builder Center
A 78.4% Blockage Is Not the Finish Line: Building DrainWatch

A 78.4% Blockage Is Not the Finish Line: Building DrainWatch

What began as an idea to detect blocked drains through public CCTV imagery turned into a much bigger engineering challenge. This is the story of building DrainWatch, the late nights, frustrating integration gaps, and the lessons I learned about turning AI predictions into trustworthy, actionable municipal workflows.

Series: DrainWatch (2 articles)

  1. 2
    A 78.4% Blockage Is Not the Finish Line: Building DrainWatch This article
There is something strangely frustrating about spending hours building a system, opening it in the browser, and realizing that the most important part still does not work.
The page looks polished. The buttons are aligned. The dashboard has all the right sections. The build passes.
Then you try to follow the actual workflow, and something is missing.
The image cannot be submitted. The map does not behave like a real map. The result is still hard-coded. The screen looks finished, but the system behind it is not.
I experienced this more than once while building DRAINWATCH, an AI-powered municipal drainage monitoring system designed to detect blockages from existing public and municipal CCTV imagery.
There were nights when I worked through one problem only to discover two more. Sometimes the progress was obvious. Other times, I spent hours questioning whether I had actually moved forward.
This is not a story about building a perfect AI model in a weekend. It is about trying to turn a promising idea into an operational system, getting stuck in the less glamorous parts of engineering, and learning why a model prediction is only the beginning.


The idea: Make existing cameras more useful

Urban drainage problems are not always discovered when they begin. A drain can gradually accumulate waste, restrict water flow, and become a serious concern before someone notices the condition and raises an alert.
Meanwhile, cities already have cameras monitoring roads and public infrastructure. The question that motivated DRAINWATCH was simple:
Could we use existing camera imagery to identify drainage blockages automatically and help the relevant authorities respond sooner?
The intended system would analyze relevant CCTV frames, estimate blockage severity, flag concerning conditions, and bring them to the attention of municipal operators.
Rather than stopping at a prediction, the system would connect detection to an operational workflow:
Camera imagery → AI analysis → Blockage detection → Alert → Verification → Incident → Dispatch → Resolution → Audit
That final sequence mattered to me. Detecting something wrong is useful, but it is not the same as getting someone to fix it.
A percentage on a screen cannot clear a drain. A field crew, equipped with the right information and operating through a traceable workflow, can.
That became the central idea behind DRAINWATCH.

What does the AI actually need to understand?

A drainage image contains more than a collection of objects. It contains a physical space in which different visual regions have different operational meanings.
DRAINWATCH is designed around three segmentation classes:
  • Structural / Concrete: The drain's structural surfaces.
  • Flowing Water: Water moving through the drainage area.
  • Solid Waste: Debris and accumulated waste that may contribute to blockage.
The definition of the relevant drain region is important. A model should not treat the surrounding road, walls, vegetation, or irrelevant parts of a frame as drain blockage.
The result is then mapped to the severity thresholds used by DRAINWATCH:
Blockage percentage
Severity
Below 40%
Normal
40% to below 70%
Warning
70% or higher
Critical
Consider an illustrative detection for asset D-1042: 78.4% blockage, classified as Critical.
That tells an operator something important, but it does not answer every question. Where did the frame originate? When was it captured? What visual evidence supports the result? Was the analysis reliable? Has an operator reviewed it? Does an incident exist? Has anyone been dispatched?
Those questions shaped the rest of the product.

The first reality check: A beautiful interface can still be broken

One of my biggest lessons came from working on the frontend.
I built a V1 interface in Figma and brought it into the project's  frontend/  directory. This gave me a much stronger starting point for the visual experience: the command center, inspection review, incident management, dispatch workflow, operational map, history, and system health.
For a while, it was tempting to judge progress by how complete the screens looked.
But I eventually had to ask a harder question:
Could someone actually use this application to complete the job it claimed to support?
The answer exposed gaps that screenshots could not reveal.
An image-analysis interface needed a real file-selection and submission workflow, not merely a placeholder suggesting that an image could be uploaded.
The map needed to be an actual interactive geographic map, not just something that looked map-like in a design.
A displayed detection had to represent the selected record rather than repeat a convenient hard-coded example. And actions such as verifying a detection, creating an incident, assigning a crew, or completing a work order needed to change application state instead of simply making the interface look busy.
These details were not as visually exciting as designing the dashboard. They were also the difference between a prototype and a useful product.
I learned to stop asking only, "Does this screen look finished?"
I started asking, "What actually happens when someone clicks this?"

The frustrating middle: Where progress stopped being linear

Working day and night on a project has a very different feel from presenting the final result.
When everything is working, a feature can take minutes to demonstrate. When it is not, the same feature can consume an entire evening.
A failure may not even be where it first appears. A frontend can display a request correctly while the API contract does not match. A build can succeed without proving that the browser can complete the workflow. A map can render markers while those markers have no reliable relationship to the records they are supposed to represent.
I encountered the broader version of this problem repeatedly: the visual layer, the operational logic, and the underlying services had to agree.
As the person carrying much of the implementation forward within the team, I often had to switch between different roles: thinking about the user experience, tracing frontend behavior, inspecting API boundaries, checking model integration, and testing operational state transitions.
That context switching was exhausting.
There were moments when I wanted to call something finished simply because it finally looked right. There were also moments when another missing connection made the entire system feel further away than it had the previous night.
The way out was not another round of cosmetic changes. It was to break the problem into smaller, verifiable steps.
Instead of asking whether DRAINWATCH was finished, I asked whether a specific path through it worked.
Could an operator select a real image? Could the backend receive it? Could the configured model process it? Could the interface display the actual result? Could that result be reviewed and connected to a record?
That approach did not make the work effortless. It made the next step clearer.

Making the map part of the system, not just part of the design

A drainage monitoring platform is inherently geographic. An alert without a reliable location is incomplete.
The map therefore needed to do more than decorate the Overview page. It needed to connect drainage assets, monitoring sources, detections, incidents, and field crews.
DRAINWATCH uses Leaflet with geographic map tiles and interactive markers. Selecting a record should open the relevant operational context, and the record should lead back to the corresponding inspection, asset history, incident, or dispatch workflow.
This introduced a deceptively important distinction: the location of a camera, the location of a drain, and the current location of a field operator are not necessarily the same thing.
That sounds obvious when written down. It is easy to blur the distinction when building a quick prototype.
For source registration and other location-dependent workflows, I also wanted people to select a position on a map or use the browser's location service when appropriate, rather than expect them to know latitude and longitude.
The broader lesson was that geographic data is not merely a visual property. It is part of the application's underlying operational truth.


The workflow after the prediction

The most important design decision was to avoid treating the AI output as the final operational decision.
DRAINWATCH separates the model's assessment from the actions taken by a human operator.
The intended progression is:
1. Detection
A frame is analyzed and a blockage estimate is produced.
2. Verification
An operator examines the evidence and determines whether the detection should be accepted.
3. Incident creation
Once the required verification is complete, the detection can become an operational incident.
4. Dispatch
A crew can be assigned, with a destination, priority, field instructions, and relevant response information.
5. Resolution and audit
The crew records the work performed and supporting evidence. Work-order completion remains distinct from the separate decision to close the incident.
This separation matters because model severity, operator verification, incident state, and work-order state describe different things.
Combining them into one status would make the interface simpler in the short term, but it would make the operational history less reliable.
DRAINWATCH is designed to preserve those distinctions, connect related records, and record important actions in an audit trail.
The goal is not merely to tell an operator that a drain may be blocked. It is to make the subsequent response understandable and traceable.


Where AWS fits into the path toward a dependable system

Building an application and operating it reliably at scale are different challenges.
For a CCTV-based monitoring system, the cloud architecture needs to account for image storage, analysis workloads, structured operational records, service failures, and access control.
A potential AWS deployment architecture for DRAINWATCH could separate these responsibilities:
  • Amazon S3: Store inspection frames, segmentation outputs, and submitted field evidence.
  • Amazon SQS: Buffer analysis jobs so ingestion and model processing can be decoupled when asynchronous processing is needed.
  • Amazon ECS on AWS Fargate: Run containerized API and worker services, subject to the model's compute requirements.
  • Amazon RDS for PostgreSQL: Store related entities such as sources, assets, inspections, incidents, work orders, and audit records.
  • Amazon CloudWatch: Collect logs, monitor processing failures and latency, and support operational alarms.
  • AWS IAM: Apply least-privilege access to the services and data.
The architectural principle is more important than the list of services: store large evidence files separately from structured records, give related records stable identifiers, and make processing failures observable rather than silently losing them.
The appropriate deployment choices still need to be validated against actual workload, cost, latency, and model requirements. Listing a service in an architecture does not mean it has been deployed or tested.
For a system that is supposed to alert authorities, that distinction matters. The monitoring pipeline must be dependable enough to report when it cannot analyze an image, when a source stops providing usable frames, and when a service becomes unavailable.
A missing frame should not quietly become an all-clear status.
Note: The AWS services above describe a proposed deployment path, not a claim that every component is already running in production.

The engineering standard I came to care about

As DRAINWATCH grew, my definition of a successful implementation changed.
A passing build is useful. A well-designed interface is useful. A segmentation result is useful.
None of those alone proves that the system is ready for operational use.
A more meaningful test is an end-to-end scenario:
A monitoring source provides an image. The analysis service processes it. The result is associated with the right source and asset. The operator reviews the evidence. A verified detection becomes an incident. The incident can be dispatched. Field work is recorded, and the history remains traceable.
Each transition needs to work, and each record must refer to the correct thing.
The same standard applies to authentication and administrative access. Hiding a button is not authorization; the backend must enforce permissions. Likewise, showing a successful message after a failed request is not a minor interface defect. It misrepresents the system's state.
These are not the parts of a project that usually make the most impressive screenshot. They are the parts that make the screenshot worth believing.


What I would tell someone building a similar project

If I had to start this kind of project again, I would keep a few lessons close.
Start with the full operational journey. Define what happens before and after the model prediction, not just the model's input and output.
Make one real workflow work early. A small path from image to genuine API response is more informative than ten polished screens backed by sample data.
Treat maps and identifiers as engineering concerns. Correct associations between sources, assets, incidents, and crews are essential to trustworthy behavior.
Keep model results separate from human decisions. A confidence value is evidence, not authorization to take every downstream action.
Never confuse compilation with validation. A successful build tells you the code compiles. Browser testing and end-to-end checks tell you whether the system behaves as intended.
And perhaps most importantly: do not hide every setback when explaining a technical project. The difficult parts often contain the most useful lessons for another builder.

Still building, but with a clearer purpose

DRAINWATCH started with a straightforward ambition: use existing camera imagery to make blocked drains easier to identify and respond to.
The engineering challenge became much larger once I considered everything between the first frame and the eventual field response.
I still think about that illustrative 78.4% blockage reading. It is a useful signal, but it is not the outcome I want the project to be measured by.
The outcome is whether the right evidence reaches the right person, whether that person can make an informed decision, and whether the response can be followed all the way through to resolution.
Working on this as the person carrying much of the implementation forward has tested my patience more than once. There were late nights, frustrating gaps between what I expected and what actually worked, and plenty of moments when progress meant fixing something nobody would notice in a demo.
But that experience changed how I approach building software.
I no longer see the finished interface as the finish line.
The real finish line is a system whose output someone can trust enough to act on—and whose actions can be explained afterward.
That is what I am trying to build with DRAINWATCH, one working connection at a time.

Series: DrainWatch (2 articles)

  1. 2
    A 78.4% Blockage Is Not the Finish Line: Building DrainWatch This article
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