The AI watched 30 people die at Kumbh Mela. Nobody warned the pilgrims. Here’s what we built.
KumbhSafe using AWS Bedrock agents, Aurora DSQL, DynamoDB, and Vercel to protect 80 million pilgrims at Nashik 2027.
The AI watched 30 people die at Kumbh Mela. Nobody warned the pilgrims. Here’s what we built.
KumbhSafe using AWS Bedrock agents, Aurora DSQL, DynamoDB, and Vercel to protect 80 million pilgrims at Nashik 2027.
January 29, 2025. Predawn. Prayagraj.
Over a million people were moving through darkness toward the Sangam — the confluence of three sacred rivers — for the Amrit Snan, the most auspicious bathing day of the Maha Kumbh Mela. Somewhere in the river of bodies, pressure built. A gap closed. People fell. The crowd behind them didn’t know. Couldn’t know. More than thirty people were crushed to death.
The cameras saw it. The AI surveillance system that the government had spent crores deploying — 2,300 CCTV feeds, computer vision, real-time density analytics — was watching the whole thing happen. The data existed. The warning never left the server room.
We read the Kumbhathon Innovation Foundation’s field report on Prayagraj weeks later. It’s forty-seven pages of what went wrong, why it almost went worse, and what might go differently at Nashik 2027. One sentence in particular stopped me cold:
“In the absence of signage and sufficient navigation tools, the police personnel deployed became the sole reliable point of contact to guide our way through the expansive mela shetra.”
A police officer. The human equivalent of a 404 error. That was the state of the art for the world’s largest human gathering.
We built KumbhSafe because of that sentence.
The problem nobody is talking about
Nashik 2027 gets mentioned in the same breath as Prayagraj 2025, as if they’re comparable events. They’re not. Nashik is harder in almost every way.
Prayagraj happens in dry winter. Nashik happens during the monsoon — June through September 2027, peak Maharashtra rainfall season. The Godavari river, already narrow and fast at the Ramkund ghats, rises without much warning.
Prayagraj has flat alluvial plains around the Sangam. Nashik has hills, a dual-city layout, and a narrow mountain road connecting the two event centers 30 km apart.
But the thing that actually keeps me up at night is the Kushavart Kund in Trimbakeshwar.
The Kushavart Kund is the sacred pond where the core Kumbh snan is performed at Trimbakeshwar. It is 75 feet by 75 feet. That’s roughly the size of a tennis court. At maximum safe crowd density, it holds around 1,900 people at a time. On the main Amrit Snan day in 2027, 7.5 million pilgrims are expected to make their way to this pond.
I did the math several times because it seemed wrong. It’s not wrong. One pond. 1,900 safe. Seven and a half million pilgrims in a single day.
And unlike Prayagraj, where the crowd had the open Sangam riverfront to spread across, Kushavart is hemmed in by a temple complex and hillside buildings. There is nowhere for the overflow to go.
What we actually built
KumbhSafe is a real-time crowd safety platform. Six AI agents, built with the Strands Agent Framework and deployed on AWS Bedrock AgentCore, watch every zone across both cities simultaneously. When crowd density hits dangerous levels, the system acts — zones go on hold, pilgrim SMS messages go out in their language, ambulances get dispatched, the NDRF gets notified.

The five-step pipeline is: sense the crowd, understand what the data means, decide what to do, act on that decision, and give every authority a unified command view.
Simple to say. The architecture to make it actually work at 80 million people is not simple.
The database decision
The hardest call we made was splitting the data layer into two stores that do completely different things.
DynamoDB handles everything operational and real-time. Zone density updates arrive every 30 seconds from 12 zones across two cities — we’re talking 200,000 write operations per hour on peak days. DynamoDB on-demand capacity absorbs that burst without any provisioning decision from us. We use a pattern I keep coming back to: every zone gets two writes per density update. One overwrites a LATEST item for instant current-state reads. One writes a timestamped snapshot for history queries, with a 7-day TTL. DynamoDB Streams off the LATEST item trigger every downstream agent action.
Aurora DSQL handles everything relational. Platform configuration, user management, zone thresholds, SOP templates, notification templates in 6 languages, audit logs. We chose Aurora DSQL specifically for its active-active multi-region setup — Mumbai as primary, Singapore as DR, with zero RPO. During Amrit Snan day, if the Mumbai region has any issue, operators in both cities keep working. The configuration layer cannot be a single point of failure on the most dangerous day of the event.
The reason I’m spelling this out: people ask why we didn’t just use one database. Because the write patterns are completely different. DynamoDB writes are hot, flat, key-value, sub-10ms — zone density snapshots, ambulance GPS pings, pilgrim check-ins. Aurora writes need SQL joins, strong consistency across tables, and a queryable audit trail. A single database that tries to do both well usually does neither particularly well.
Six agents, one orchestrator
The agent layer is where the platform gets interesting, and also where we made what I think is the most important design decision.
We have six agents:
CrowdSentinel watches zone density every 30 seconds. When a zone hits RED (6.5 people per square metre), it creates a HIGH alert and notifies operators. When it hits BLACK (above 6.5, or Kushavart exceeds 1,900 people), it creates a CRITICAL alert, activates entry hold, notifies NDRF, and invokes RouteOracle.
RouteOracle calculates safe alternative paths when zones are congested and sends rerouting SMS to every pilgrim registered in the danger radius — in their own language.
FloodWatch polls the Godavari water level every five minutes during monsoon months. If it detects the river rising more than half a metre per hour, it triggers ghat closure alerts proactively. Not reactively.
MedEvac handles SOS triggers. Given a pilgrim’s location, it identifies the nearest available ambulance, dispatches it, creates a green corridor request to the police, and confirms response — in under 8 seconds.
LostConnect handles missing persons. Multilingual voice bot, Rekognition facial recognition against registered pilgrim photos, SMS notification when there’s a match.
CommandBridge is the orchestrator. It has one tool no other agent has: invoke_child_agent. When events in both cities peak simultaneously, CommandBridge coordinates the 30 km corridor between them — which ambulances go where, where the mutual-aid boundary sits, when to call NDRF to the midpoint rather than committing them to either city.
The important design decision I mentioned: the most critical safety rules are not in the agents at all.
The Kushavart hard cap — if the kund exceeds 1,900 people, activate entry hold immediately — is in the DynamoDB zone-stream Lambda processor as a direct conditional check. It fires synchronously on every density write. No agent invocation. No AI reasoning. No latency spike. Code runs or it doesn’t.
The NDRF notification for critical alerts is in the alert-stream Lambda. It fires on every critical alert INSERT, sends an HMAC-signed webhook to the NDRF external API, regardless of whether any agent is running.
I keep coming back to this decision during the build. The seductive thing about having capable agents is that you want to give them everything. But an agent can have a response time spike. It can be throttled. The system prompt can have an edge case you didn’t think of. When the failure mode is a stampede at a 75×75 foot pond, “the agent will handle it” is not a sufficient safety architecture. Code you can read, test, and trace is.
The frontend: v0 and Cloudscape
The ICCC Command Dashboard was built entirely using Vercel v0, prompted with the Cloudscape Design System throughout.
Cloudscape is AWS’s own operational UI framework. It has components built for exactly this kind of command-centre context: <Table> with bulk actions, <LineChart> for live density trends, <Flashbar> for streaming critical alerts, <StatusIndicator> for agent health, <AppLayout> with a navigation shell. The reason we used it instead of building from scratch or reaching for shadcn: our operators will be working 14-hour shifts on mobile networks in monsoon conditions. They need something that works, loads fast, and reads clearly at 3am.
The v0 prompt was specific — every screen, every component, every data type, every interaction. What you get from v0 when your prompt is vague is a generic dashboard. What you get when your prompt describes a dual-city live zone heatmap with density severity color coding, a right-column alert feed with SOP checklists that auto-attach by alert type, and a Bedrock agent monitor with raw AgentCore config view — is actually that. The quality ceiling on v0 is the quality floor on your prompt.
AppSync subscriptions push zone density updates to every connected dashboard without polling. When CrowdSentinel activates an entry hold on Kushavart at 11:03am, every ICCC operator in both cities sees it in the same second.
What took the longest
The system prompt engineering for CrowdSentinel went through eleven versions.
The first few versions were too aggressive — they created duplicate alerts for the same zone in rapid succession during sustained RED conditions, flooding the alert queue and training operators to ignore it. The later versions overcorrected and became too conservative, waiting for confirming signals before acting.
The version that worked required explicit negative examples. “Do NOT create a second alert for the same zone-type combination within 10 minutes unless severity escalates” turned out to be as important as the positive rules about when to act. The agents only know what you tell them. Telling them when not to do something is just as load-bearing as telling them when to.
The other thing that took longer than expected: the offline-first problem. Pilgrims near Kushavart Kund often have minimal mobile connectivity. Sending them an SMS reroute when the zone hits RED assumes their phone receives the message within a useful time window. Our partial answer is QR kiosk terminals distributed through the mela grounds with cached zone information, and delivery receipts on SNS messages that escalate undelivered alerts to WhatsApp group broadcasts. It’s not a complete solution. I’m not going to claim it is.
The multi-user system
One thing that didn’t exist in our initial design but became central: role-based access control that maps to how emergency management actually works.
Seven roles: Super Admin, Org Admin, ICCC Operator, Field Officer, Medical Staff, Police Coordinator, Viewer. Twenty-two distinct permissions across zones, alerts, pilgrims, medical cases, agents, and platform config. Role is stored as a Cognito custom attribute alongside city_access — which means a field officer in Nashik can never see Trimbakeshwar zone data, enforced at the Lambda handler level, not just filtered in the UI.
The city access filter was an afterthought that turned out to matter. During incidents, operators in each city need clarity about their city, not noise from the other one. When both cities are at RED simultaneously, the people who need to see everything are CommandBridge operators, not everyone.
The Super Admin layer seeds the entire platform: 12 zone configs with custom density thresholds (Kushavart gets significantly lower thresholds than the defaults), 6 agent configs with model IDs and system prompts, 36 notification templates (6 event triggers in 6 languages), 28 SOP templates. The whole platform is operational within 10 minutes of running the bootstrap script.
What I’d tell someone building this
Three things that turned out to be true:
The most important safety systems are the ones that work when AI doesn’t. Agents enhance the platform. They do not guarantee it. Code guarantees it.
Database design is a safety feature. The LATEST SK pattern in DynamoDB — writing two items per density update — meant we could serve real-time zone state in a single strong-consistency GetItem without building a caching layer. If we’d appended density readings to a list in one item, we’d have hit the 400KB DynamoDB item size limit during peak hours and started silently dropping data.

Language is infrastructure. SMS rerouting in English to a Marathi-speaking elderly pilgrim is not a message. It’s noise that gets ignored. The 36 notification templates were not a nice-to-have.
What’s next
We’re working with the Kumbhathon Innovation Foundation to present KumbhSafe to NTKMA — the Nashik-Trimbakeshwar Kumbh Mela Authority — before the end of 2026. The architecture is the pitch: it’s not a prototype. It’s built to run.
After Nashik, the platform config model means any large public gathering — Haridwar Kumbh 2027, Ujjain Kumbh 2028, Republic Day parades, election rallies — can be onboarded with a new event config and a bootstrap script. We want KumbhSafe to become generic infrastructure, not a one-time build.
The thing that gets me is simpler than any of that: the Prayagraj surveillance cameras were watching when thirty people died. The data existed. It just never made it to anyone who could do something with it. That’s a solvable problem. We’ve tried to solve it.
Nashik 2027. 80 million pilgrims. A monsoon. A 75-foot pond.
We hope nobody needs to use the critical alert path. But it’s there, it’s tested, and it will fire whether the agents are running or not.
KumbhSafe was built at the H0: Hack the Zero Stack with Vercel v0 and AWS Databases AWS Databases & Vercel Hackathon.
Thanks to the Kumbhathon Innovation Foundation for their Prayagraj 2025 field report, which is the most honest and useful piece of research we found on what actually happens when the world’s largest gathering meets insufficient information infrastructure.
#H0Hackathon
메타데이터
- post_id
- 973f13d686a7
- slug
- the-ai-watched-30-people-die-at-kumbh-mela-nobody-warned-the-pilgrims-heres-what-we-built-973f13d686a7
- url
- https://medium.com/@akashtalole/the-ai-watched-30-people-die-at-kumbh-mela-nobody-warned-the-pilgrims-heres-what-we-built-973f13d686a7
- canonical_url
- https://medium.com/@akashtalole/the-ai-watched-30-people-die-at-kumbh-mela-nobody-warned-the-pilgrims-heres-what-we-built-973f13d686a7
- author_url
- https://medium.com/@akashtalole
- status
- ok
- fetched_at
- 2026-07-09 15:12:33