Get Started
Medical Booking Platform

Medical Booking Platform

Architecting a complex medical appointment system with master bookings, partial cancellations, and automated payouts via RazorpayX.

December 15, 20258 min read
Next.jsNode.jsMySQLRazorpayXSystem Design

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

  1. Patient requests cancellation of one or more individual bookings
  2. System calculates refund amount based on cancellation policy:
  3. Razorpay Refund API is called for the calculated amount
  4. Individual booking status updated to cancelled
  5. If all individual bookings cancelled → master booking auto-cancels
  6. 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

  1. When an individual booking is marked completed, a payout job is queued
  2. System calculates doctor's share (total amount - platform commission)
  3. RazorpayX Payout API transfers funds to the doctor's linked bank account
  4. Payout status is tracked: queued → processing → processed / failed
  5. 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

  1. Design for partial states early — the master/individual booking split should have been in v1 architecture, not retrofitted
  2. Idempotency is non-negotiable for payment operations — Razorpay webhooks can fire multiple times
  3. RazorpayX has strict KYC requirements — budget time for vendor onboarding flow
  4. Admin visibility matters — the reconciliation dashboard became the most-used feature by the ops team
  5. Test with real money early — sandbox behavior differs from production in subtle ways (especially payout timings)