A fully autonomous recovery engine — it classifies every revenue leak, decides the recovery action, and executes through the right channel. Merchants configure credentials and deploy — the pipeline handles classification, routing, and messaging autonomously from there.
Indian merchants lose revenue from three separate holes. Current recovery tools handle them separately with no shared intelligence about why the payment failed.
| Competitor | Approach | Limitation |
|---|---|---|
| Stripe ↗ | Smart Retries + card updates (55% recovery) | Email-only dunning, retry and dunning independent |
| Adyen ↗ | Multi-armed bandits for retry timing | Retry-only, no customer communication |
| Cashfree ↗ | "Relay" AI agent for failed payments + carts | Single-agent, not a pipeline |
| Recurly ↗ | Intelligent Dunning ML (70-80% recovery) | Subscriptions only |
| Chargebee ↗ | Pre-dunning workflows (30-40% + 15-22%) | Subscriptions only |
| Most others | Fixed retry schedules, email-only | No multi-channel, no classification |
Everyone focuses on retry mechanics. Nobody combines diagnostic intelligence with personalized multi-channel recovery across all three leak types in a single engine.
Every decision here was deliberate. Let me walk you through how I see this.
organic_recovery, not recovered. I track "sent" not "delivered" because I haven't built delivery receipts yet. I'd rather be honest than inflate.acks_late=True, reject_on_worker_lost=True, exponential backoff, distributed locks, conditional DB updates, and a reserve-before-send pattern with idempotency keys that prevents double-sends on worker crashes. If Razorpay shipped this tomorrow, the architecture wouldn't need rewriting.I built one autonomous engine that handles all three. Same pipeline, every time. Zero manual intervention.
payment.failed webhook/webhook/recovery-routermax_attempts computed per eventdegradation_pathEach one gets different treatment - different channel, different timing, different attempt budget.
| Category | Probability | Channel | Timing | Max Attempts |
|---|---|---|---|---|
| UPI Timeout | 75–85% | Immediate | 3–5 | |
| Bank Downtime | 70–85% | 30 min delay | 3–5 | |
| Gateway Error | 80–90% | 5 min | 3–5 | |
| Card Expired | 40–60% | Immediate | 3–4 | |
| Insufficient Funds | 30–50% | SMS | 4 hour delay | 3 |
| User Cancelled | 20–40% | 1 hour | 2 | |
| Unrecoverable Decline | 0% | None | - | 0 |
| High Intent Abandonment | 30–50% | 1 hour | 3 | |
| Browse Only Abandonment | 5–10% | None | - | 0 |
| Recently Overdue (1-7d) | 60–80% | Immediate | 3–5 | |
| Moderately Overdue (8-30d) | 30–50% | Immediate | 3–4 | |
| Long Overdue (30d+) | 10–20% | - | 2 |
I wired up FastAPI + Celery Worker + Celery Beat + React Frontend + Redis + Supabase. Every operation runs through my real async pipeline.
| Component | Technology | Why |
|---|---|---|
| API | FastAPI | Async, auto-docs (Swagger), Pydantic validation |
| Task Queue | Celery + Redis | Late ACK, crash recovery, periodic scheduling (Beat) |
| Database | Supabase (PostgreSQL) | RLS, REST API, PostgreSQL triggers |
| AI Gateway | OpenRouter | Multi-model, no vendor lock-in, single API |
| AI Models | Claude Haiku 4.5 → Gemini 3.7 Flash → GPT-4o-mini | Speed-first fallback: fastest first, cheapest last |
| Payments | Razorpay Orders API | Unlimited orders (vs 30-link Payment Links limit) |
| Green API + Twilio | Green API for personalized text, Twilio as template fallback | |
| SMS | Twilio | Industry standard, trial limits restrict testing |
| Resend | AI-personalized HTML with branded template | |
| Frontend | React 19 + Vite 8 + Tailwind 4 | Fast HMR, Razorpay UI clone |
| Live Updates | REST API polling | Dashboard auto-refreshes every 15-30s via backend API |
| Cache/Locks | Redis (6 roles) | Broker, cache, dedup, rate limit, locks, PII store |
hmac.compare_digest()json.dumps escaping.eq("status","pending") on every updatedelivery_failure_count stops infinite retries on unreachable contactsI did the research before writing a single line of code. Here's how it played out.
These are the bugs that almost took me down. I'm sharing them because this is what separates production systems from demos.
action to "give_up" instead of "send"attempt_count < max_attempts_send_delayed and Beat escalation both picked up the same event.eq("status", "pending")skip_reason=null - my code never does thatmax_attempts = 5 for every eventcompute_max_attempts()content_sid templatesattempt_count only increments on successful sends — provider rejections left it at 0attempt_count < max_attempts) always passed — the event could never exhaustdelivery_failure_count — a separate counter for hard provider rejectionsdelivery_failure_count > max_attempts → mark exhausted with skip_reasonhas_any_sent), skip the gate — the contact works| Scenario | Today | With Recovery Router |
|---|---|---|
| Payment fails | Merchant follows up manually, or doesn't | AI classifies the failure and sends a personalized message within seconds |
| Cart abandoned | No recovery - lost revenue | High-intent carts get recovery; browse-only ones get zero attempts (saves cost) |
| Invoice overdue | Manual reminders, takes weeks | Automated within hours - tone escalates with urgency |
| Customer ghosts | 40% never come back | Multi-channel outreach (email → SMS → WhatsApp) within the optimal window |
I walk you through the architecture, live demos with dynamic budgets, safety mechanisms, the Ghost Writer bug story, honest metrics, the test suite, and the future of agent-to-agent recovery.
| Section | What's Shown |
|---|---|
| Opening | Personal intro — why I picked Track 3, the insight behind Recovery Router |
| Architecture | Six-component architecture with decision reasons for each technology choice |
| Live Demo | Simulator scenarios showing dynamic budgets, then real Razorpay test-mode checkout |
| Dashboard | Events page walkthrough — different classifications, budgets, and AI reasoning |
| Safety | 18 defense layers, 3-layer give-up prevention, then the Ghost Writer bug story |
| Analytics | Honest metrics — organic vs recovered, code overlay for ghost recovery prevention |
| Testing | 397-test suite run + CI pipeline + bug war stories |
| Ecosystem | Where Recovery Router fits in Razorpay's product suite + the build journey |
| Future | Agent-to-agent recovery — why traditional channels fail when the payer is an AI agent |
Split into unit (247 offline, no credentials), live (92 integration, real services), e2e (31 standalone flows), and frontend (27 component tests). Unit tests verify every backend function anywhere. Live tests hit real Redis, real Supabase, real AI. CI runs 274 tests on every push.
I'd rather tell you what's missing than pretend it's all done.
Recovery Router isn't a standalone tool - it's designed to sit inside Razorpay's existing ecosystem and fill the gap after a payment fails.
payment.failed webhooks - that's my primary entry pointRazorpay's Agent Studio launched AI agents that initiate payments. When the payer is also an agent, who do you send the WhatsApp to?
"I didn't build a hackathon project. I built what I would build if I were a Razorpay engineer assigned to solve this problem on Day 1."