Vishal.dev
Back
RGD School — Multi-Tenant School Management SaaS — live site preview
Full-Stack

RGD School — Multi-Tenant School Management SaaS

Production multi-tenant school management platform with student/staff management, attendance tracking, fee handling with Razorpay, exam management, and role-based access control across subscription tiers.

Next.js 15TypeScriptReact 18PostgreSQLPrisma 6NextAuth.jsTailwind CSS 4Radix UIRazorpaySupabaseRedisFramer Motion
4
User roles
12+
Core modules
5
Subscription tiers
<80ms
Page load time

Domain Knowledge

What problem this project solves

School management is deceptively complex. Fee management alone requires installment plans, early-bird discounts, sibling discounts, late payment penalties, scholarship adjustments, and refund processing. Attendance tracking needs period-level granularity (not just day-level) to handle students who are present in some classes but absent in others. Multi-tenancy requires data isolation per school while sharing the same codebase and infrastructure. The subscription tier system adds another dimension: feature flags, usage limits, and payment integration must work correctly across all tiers.

Architecture

How the system is structured

The system uses a modular monolith with clear domain boundaries: Student Management, Academic Tracking, Fee Management, Examination, and Reporting. Multi-tenancy is enforced via slug-based routing — each request includes the school slug, which scopes all database queries. Authentication uses NextAuth.js with credentials provider and Prisma adapter. Role-based middleware enforces permissions at both API and data levels. Background workers handle report generation and fee reminders. Razorpay handles payment processing with webhook-driven settlement.

Data Model

Schema design and data flow

The domain model centers on the School entity, which owns Students, Staff, Classes, Fees, Exams, and Results. Students connect to Attendance, Fee, and Exam entities. Fee records support installments, discounts (sibling, merit), late fees, and scholarship adjustments. Exam results support multiple subjects, grade boundaries, rank calculation, and report card generation. Subscription tiers (Free, Starter, Basic, Pro, Enterprise) control feature access and usage limits per school.

Key Challenges

Hardest problems encountered

Fee management was the most complex module — real schools don't charge flat fees. The engine handles installment plans with varying due dates, partial payments, late fees that compound daily, sibling discounts that cascade, and scholarship adjustments that modify the base fee. Razorpay integration required handling webhooks for payment confirmation, refund processing, and subscription renewal. Student transfer between sections mid-year required careful handling of attendance and fee history to maintain data integrity.

Scaling Strategy

How the system grows

The system serves multiple schools on shared infrastructure. PostgreSQL handles relational data with connection pooling. Redis caches school-specific data (fee structures, class schedules, member lists) with TTL-based invalidation. Vercel cron jobs handle student promotion and fee reminder scheduling. Background jobs prevent slow operations (report generation, bulk SMS) from blocking HTTP requests.

Security

Defense-in-depth approach

Four role levels (Admin, Staff, Student) with granular per-module permissions. School data isolation enforced at the query level — every database query includes a school slug filter. NextAuth.js session management with CSRF protection. Upstash Redis rate limiting on login attempts. Razorpay webhook signature verification. Supabase storage with signed URLs for file uploads. All API endpoints enforce authentication and authorization before data access.

Failure Handling

Resilience and recovery

Fee payments use idempotency keys to prevent double-charging. Report generation retries on failure with exponential backoff. Attendance saving is transactional — if saving 40 students' attendance fails, the entire batch rolls back. Razorpay webhook processing is idempotent — duplicate webhooks don't create duplicate transactions. Database connection failures trigger graceful degradation with cached data.

Observability

Monitoring and debugging

Dashboard tracks fee collection rates, attendance trends, class performance comparisons, and exam result distributions. Structured logging with correlation IDs across request boundaries. Audit logs track who modified student records, fee waivers, and grade changes. Razorpay payment status tracked with reconciliation. Vercel deployment logs for cron job execution.

Trade-offs

Engineering decisions and alternatives

Modular monolith over microservices because the school scale doesn't warrant distributed complexity. Prisma over raw SQL for type safety and migration management at the cost of some query flexibility. Razorpay over Stripe for Indian market focus. Supabase storage over S3 for simpler integration. Background jobs over cron for retry and observability. slug-based tenancy over schema-per-tenant for simpler deployment.

Architecture Decisions

Key choices and what was rejected

Decision
Chosen
Rejected
Architecture
Modular monolith with domain boundaries
Microservices (premature complexity)
Tenancy
Slug-based routing with query-level isolation
Schema-per-tenant (migration complexity)
Payment gateway
Razorpay (Indian market)
Stripe (less local support)
File storage
Supabase with signed URLs
S3 (more configuration)

Senior-Level Topics

Concepts this project explores

Multi-Tenant ArchitectureDomain-Driven DesignRole-Based Access ControlSubscription SystemsPayment IntegrationState MachinesBulk OperationsReport Generation