Project Overview
This project was built for a healthcare startup that needed a robust appointment booking system supporting multiple doctors, clinics, and specializations.
The key challenge was designing a Master Booking architecture — where a single patient visit could contain multiple individual bookings (lab tests, consultations, follow-ups), each independently manageable.
Client: Indian Healthcare Startup Timeline: 3 months Role: Full-Stack Developer (Solo)
The Problem
The client's existing system was a basic form-based booking tool with no support for:
- Grouped bookings — patients had to make separate bookings for each service
- Partial cancellations — canceling one service meant canceling the entire visit
- Automated refunds — all refunds were processed manually via bank transfers
- Doctor payouts — vendors/doctors were paid manually at month-end
This led to high operational overhead, frequent customer complaints, and delayed payments to healthcare providers.
Architecture & Tech Stack
Tech Stack - Frontend: Next.js 14 (App Router) + Tailwind CSS - Backend: Node.js + Express REST API - Database: MySQL with Prisma ORM - Payments: Razorpay (Pay-In) + RazorpayX (Payouts) - Auth: NextAuth.js with role-based access (Patient, Doctor, Admin) - Hosting: Vercel (Frontend) + Railway (Backend + DB)
Data Model
MasterBooking
├── id, patientId, totalAmount, status
├── IndividualBooking[]
│ ├── id, serviceType, doctorId, amount, status
│ ├── cancellationReason?, refundAmount?
│ └── payoutStatus (pending | processed)
└── PaymentTransaction[]
├── razorpayOrderId, amount, status
└── refundId?The Master Booking groups related services. Each Individual Booking tracks its own lifecycle — from scheduled → confirmed → completed/cancelled. This separation was critical for partial cancellation logic.
Partial Cancellation & Refund Logic
The most complex feature was allowing patients to cancel individual services within a master booking without affecting others.
How It Works
- Patient requests cancellation of one or more individual bookings
- System calculates refund amount based on cancellation policy:
- Razorpay Refund API is called for the calculated amount
- Individual booking status updated to
cancelled - If all individual bookings cancelled → master booking auto-cancels
- Refund status tracked asynchronously via webhook
Key Edge Cases Handled - Preventing double-refund on retry - Handling Razorpay webhook failures with idempotency keys - Admin override for manual refund adjustments - Partial refund when coupon/discount was applied to master booking
Automated Payouts with RazorpayX
Doctors and labs needed to be paid their share after each completed booking. Previously this was done manually — we automated it with RazorpayX.
Payout Flow
- When an individual booking is marked
completed, a payout job is queued - System calculates doctor's share (total amount - platform commission)
- RazorpayX Payout API transfers funds to the doctor's linked bank account
- Payout status is tracked:
queued → processing → processed / failed - Failed payouts trigger admin notifications and automatic retry (max 3 attempts)
RazorpayX Integration Details
- Used Fund Accounts to store verified bank details per doctor
- Payouts made via bank_transfer mode (IMPS/NEFT)
- Webhook listeners for payout status updates
- Daily settlement reconciliation report for admin dashboard
Results & Impact
After 3 months of development and 2 weeks of beta testing:
- 70% reduction in manual refund processing time
- 100% automated vendor payouts (previously manual)
- 4.2x increase in booking throughput due to grouped bookings
- Zero payment discrepancies in first 3 months of production
- Admin dashboard enabled real-time tracking of all transactions
The platform successfully handled 500+ bookings/month within the first quarter of launch, with plans to scale to multiple cities.
Key Learnings
- Design for partial states early — the master/individual booking split should have been in v1 architecture, not retrofitted
- Idempotency is non-negotiable for payment operations — Razorpay webhooks can fire multiple times
- RazorpayX has strict KYC requirements — budget time for vendor onboarding flow
- Admin visibility matters — the reconciliation dashboard became the most-used feature by the ops team
- Test with real money early — sandbox behavior differs from production in subtle ways (especially payout timings)