Ed-Tech
ScholarPath
Multi-tenant SaaS for India's scholarship exam market — live with paying customers.
Customer
Maharashtra MSCE scholarship exam market — parents, students, exam coordinators
Timeline
2024–Present
Status
Live in production
Capability
Stack
Outcome
Customer Context
Who they are and what world they live in
The Maharashtra MSCE scholarship exam is a high-stakes test for students in classes 5 and 8. Parents in this market are deeply invested in their child's preparation but have no structured digital tool — exam prep is fragmented across WhatsApp groups, photocopied question papers, and individual tutors. The parent is the decision-maker and the paying customer, but the student is the user. That distinction drives everything about the architecture.
The Problem
The fuzzy ask, translated
The gap wasn't 'there's no app' — there were apps. The gap was: no app understood the parent-as-gateway model. Every existing tool gave children direct accounts. But in Maharashtra's scholarship ecosystem, parents manage preparation, parents pay, and parents need visibility into progress. The real problem was building an access model that matched how families actually work, not how SaaS companies assume they work.
The Constraints
Time · Budget · Regulatory · Technical · Organizational
Parent-as-gateway: parent owns the account and manages multiple child profiles — each child may have a different exam tier and access level
Razorpay INR payments with webhook reliability in a market where payment failures are common
Mobile-first for rural Maharashtra users on older Android devices with unreliable connectivity
Generically extensible: the exam-category configuration must support rapid expansion to new exam verticals without re-architecting
Live customer support during onboarding — real users, real issues, real iteration pressure
Architecture Decisions
What I chose. What I rejected. Why.
Authentication and access model
Chosen
Parent-as-gateway: parent record owns all child sessions, child profiles inherit access from parent's tier
Rejected
Direct child authentication / per-child accounts
Why
Matches how families actually operate in this market. Simplified the threat model significantly — no child authentication surface. Supabase RLS policies scoped to parent_id rather than user_id per child.
Exam configuration
Chosen
Generic exam-category configuration table — exam type, grade level, subject, question count, timer rules all configurable per category
Rejected
Hardcoded exam types
Why
MSCE is the launch vertical but not the only one. Every configuration parameter being data-driven means adding a new exam type is a database row, not a deployment.
AI-assisted delivery
Chosen
Supabase MCP integration with Claude Code for content generation and AI-assisted development
Rejected
Manual content pipeline
Why
MCP server integration with Claude Code means content workflows run inside the development environment — schema-aware, context-aware, dramatically faster than a separate CMS.
The Hard Problem
The one thing that almost broke the deployment
Multi-tenant data isolation when one parent has multiple children with different access tiers — and the children are not paying users. Supabase Row Level Security was designed for single-user tenancy. Extending it to a parent-owns-children model required a custom access-control layer: every query scoped to the parent's subscription tier, with child profiles inheriting rather than holding their own access grants.
The Fix
Rebuilt the permission model: parent record is the tenant root. Child profiles are owned rows under the parent, with no independent authentication. Access tier is resolved at query time from the parent's active subscription, propagated to child profile reads via a parent_id join. No child can access anything their parent hasn't paid for — and no parent can see another family's data.
Production Reality
What I had to fix in week 2
Razorpay webhooks arrived multiple times for the same payment event. The initial payment handler wasn't idempotent — early users were seeing duplicate payment records. Added idempotency keys on the Razorpay order ID, with a processed_webhooks table to deduplicate before updating subscription state. Payment integration in a regulated market has more compliance edges than features.
Lessons Carried Forward
What this taught me that I apply to every deployment
Match the access model to how the customer's family actually operates — not how SaaS assumes they operate
Payment webhook idempotency is not optional in markets with unreliable payment infrastructure
Generic configuration tables pay off immediately — the second exam vertical was two database rows and one afternoon
MCP server integration with Claude Code is a legitimate force multiplier for content-heavy platforms
Customer feedback in week 1 changes the spec faster than 6 months of planning
Related Deployments