$ cd ../
PUBLISHED: MAY 2026
#fastapi#postgis#gemini ai#civic tech

Building an AI-Powered Civic Grievance System with FastAPI and PostGIS

How we architected JanSamadhan to ingest WhatsApp webhooks, route tickets dynamically to city departments, and suppress duplicate complaints using location-aware queries.

// summary (tldr)

Scale, accuracy, and geo-deduplication: key system design lessons from deploying a municipal pilot in Delhi.

Introduction to Civic Engineering

Building software for local government is completely different from building typical SaaS. In civic tech, your users aren't tech-savvy developers; they are everyday citizens reporting open potholes, water leaks, or electrical failures. The primary interface needs to be as friction-free as possible, which is why we turned to messaging interfaces like WhatsApp for ingestion.

However, behind that simple interface lies a complex routing problem. How do you take unstructured, multilingual complaints, identify where they are, figure out which of the 10+ government departments is responsible, and prevent queue flooding from duplicate reports?

This post details the system design of JanSamadhan, an automated civic routing system deployed as a ward pilot in Delhi.

---

High-Throughput Ingest with FastAPI

Our entry point is the WhatsApp Cloud API webhook. During local civic crises (such as heavy rainfall causing road flooding), webhook callbacks spike to thousands per minute. If the ingest server takes too long to respond, WhatsApp retries the callback, creating a webhook storm.

To solve this, we decoupled ingest from processing:

  • **Immediate Ack:** The FastAPI route accepts the payload, verifies the webhook signature, and immediately returns a `200 OK` status response.
  • **Task Queue Allocation:** The message content and meta metadata are pushed to an async task queue managed by **Redis** as a broker.
  • **Connection Pooling:** We optimized SQLAlchemy to reuse PostgreSQL connection sockets, keeping query latency under 10ms.
  • ---

    Geospatial Deduplication with PostGIS

    The biggest administrative problem in civic reporting is duplicate reports. If a water main bursts in a market square, fifty people might report it within an hour. Creating fifty separate work tickets wastes civic resources and clogs agency dashboards.

    We solved this using PostGIS:

    SELECT id, category 
    FROM grievances 
    WHERE status = 'open' 
      AND category = :new_category
      AND ST_DWithin(geom, ST_SetSRID(ST_Point(:lng, :lat), 436), :radius_meters);

    By querying coordinates using the `ST_DWithin` spatial query inside a strict radius (usually 50 meters), the system automatically links new submissions to the master ticket. The user is instantly registered as a subscriber to the existing issue, receiving updates without creating database overhead.

    ---

    Multilingual Classification with Gemini

    To route issues to correct departments without manual oversight, we structured our prompts to parse messy inputs into strict JSON models.

    We defined a schema using Gemini structured output:

    {
      "category": "drainage_overflow",
      "urgency": "high",
      "summary": "Overflowing sewer line causing road block at Ward 12."
    }

    The parsed JSON matches our internal database schema. Because Gemini returns standard format fields, the backend routes the grievance straight to the correct department's queue automatically.

    ---

    Conclusion

    Civic tech doesn't need over-engineered frameworks; it needs high-availability API endpoints, intelligent spatial caching, and structured routing models. JanSamadhan demonstrates how open APIs and simple open-source tools can dramatically improve urban living standards.