
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.
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
Senior-Level Topics
Concepts this project explores