Introduction
My School Education OS is an enterprise-grade, AI-first cloud ERP platform engineered for modern K-12 schools and multi-campus educational trusts. It consolidates academics, admissions, finance, LMS, staff management, hostel, transport, and parent engagement into a single multi-tenant microservices architecture.
What's Included
- 15 domain service modules — Academics, Admissions, Attendance, Finance, Examinations, LMS, Library, Transport, Hostel, HRMS, Inventory, CRM, Communication, Security, Analytics
- 7 role-based portals — Super Admin, School Owner, Principal, Teacher, Student, Parent, Accountant
- Native mobile apps — React Native Expo for Android and iOS
- REST + GraphQL APIs — Full programmatic access for integrations
- Multi-tenant isolation — Strict per-school data separation
System Requirements
| Component | Minimum | Recommended (Production) |
|---|---|---|
| CPU | 4 vCPU | 16 vCPU (AWS c5.4xlarge) |
| RAM | 8 GB | 32 GB |
| PostgreSQL | v15+ | v16 with RDS Multi-AZ |
| Redis / Cache | Redis 7.0 | AWS ElastiCache |
| Message Broker | Kafka 3.6 | Amazon MSK |
| Container Runtime | Docker Engine 24.0+ | AWS ECS Fargate |
| Node.js | v20.0.0 LTS | v20.10.0 LTS |
| Python | 3.11 | 3.12 |
| Storage | 100 GB SSD | 1 TB S3 + EBS gp3 |
Installation
Prerequisites
- Git 2.39+
- Node.js v20.10.0 LTS (use
nvm use 20) - Python 3.12
- Docker Engine 24.0+ and Docker Compose v2.20+
- PostgreSQL 15+ (or Docker image)
Clone and Setup
# 1. Clone the monorepo
git clone https://github.com/Asadxio/my-school-education-os.git
cd my-school-education-os
# 2. Install all Node.js dependencies (monorepo workspaces)
npm install
# 3. Copy environment configuration
cp .env.example .env
# Edit .env with your DB credentials, Keycloak settings, and API keys
# 4. Start infrastructure services (PostgreSQL, Kafka, Keycloak)
docker compose -f docker-compose.dev.yml up -d postgres kafka keycloak
# 5. Run database migrations
cd services/academic-service
alembic upgrade head
# 6. Start all services
npm run dev:web # Next.js frontend on :3000
npm run dev:mobile # Expo mobile on :19000
Environment Variables
| Variable | Description | Example |
|---|---|---|
DATABASE_URL | PostgreSQL connection string | postgresql://user:pass@localhost:5432/myschool |
KEYCLOAK_URL | Keycloak server base URL | http://localhost:8080 |
KEYCLOAK_REALM | Keycloak realm name | myschool |
KAFKA_BOOTSTRAP_SERVERS | Kafka broker addresses | localhost:9092 |
NEXT_PUBLIC_API_BASE_URL | FastAPI backend URL | http://localhost:8000 |
RAZORPAY_KEY_ID | Razorpay API key | rzp_test_... |
TWILIO_ACCOUNT_SID | Twilio WhatsApp SID | AC... |
Quickstart Guide
make bootstrap command after cloning to run the full setup automatically including Docker services, migrations, and seed data.# One-command bootstrap (requires Docker)
make bootstrap
# This runs:
# - docker compose up -d
# - alembic upgrade head on all services
# - npm run seed (loads demo school data)
# - npm run dev:web
Default Login Credentials (Development)
| Role | Username | Password |
|---|---|---|
| Super Admin | superadmin@demo.myschool | Demo@1234! |
| School Owner | owner@demo.myschool | Demo@1234! |
| Principal | principal@demo.myschool | Demo@1234! |
| Teacher | teacher@demo.myschool | Demo@1234! |
| Student | student@demo.myschool | Demo@1234! |
| Parent | parent@demo.myschool | Demo@1234! |
Microservices Architecture
The platform is composed of independently deployable Python FastAPI microservices, each owning its domain data. Services communicate asynchronously via Kafka events and synchronously via the API Gateway for read-heavy requests.
Core Services
| Service | Port | Responsibility | Database Schema |
|---|---|---|---|
academic-service | 8001 | Courses, timetables, grading, GPA | academics |
admissions-service | 8002 | Applications, enrollment pipeline | admissions |
finance-service | 8003 | Fees, invoices, payment gateway | finance |
attendance-service | 8004 | Attendance records, alert triggers | attendance |
lms-service | 8005 | Courses, assignments, submissions | lms |
hrms-service | 8006 | Staff, payroll, leave | hrms |
transport-service | 8007 | Routes, vehicles, GPS tracking | transport |
notification-service | 8008 | SMS, WhatsApp, email, push | notifications |
api-gateway | 8000 | Routing, auth, tenant context | — |
Kafka Transactional Outbox Pattern
To guarantee zero data loss between microservices, My School OS implements the Transactional Outbox Pattern. Instead of publishing events directly to Kafka (which can fail after a DB commit), domain events are written atomically to an outbox_events table in the same transaction as the business data.
Flow
- Service writes business record + outbox event in a single DB transaction.
- A background Relay worker polls
outbox_eventsfor unpublished rows. - Relay publishes each event to the appropriate Kafka topic.
- Consumer services process events (e.g., Notification Service sends WhatsApp alert).
- On successful publish,
outbox_events.published_atis stamped.
-- outbox_events table structure
CREATE TABLE outbox_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
aggregate VARCHAR(64) NOT NULL, -- e.g. 'student_attendance'
event_type VARCHAR(64) NOT NULL, -- e.g. 'ATTENDANCE_MARKED'
payload JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
published_at TIMESTAMPTZ
);
Multi-Tenancy Isolation
Every API request must carry an X-Tenant-ID header (UUID format). The API Gateway validates this against the authenticated user's Keycloak token claims, then injects it into the RequestContext passed to every downstream service.
WHERE tenant_id = :tenant_id. No cross-tenant data access is possible at the query layer.Tenant Context Flow
# FastAPI dependency injection pattern
from app.core.context import TenantContext
async def get_tenant_context(request: Request) -> TenantContext:
tenant_id = request.headers.get("X-Tenant-ID")
if not tenant_id:
raise HTTPException(status_code=400, detail="X-Tenant-ID header required")
return TenantContext(tenant_id=UUID(tenant_id))
Authentication (Keycloak OIDC)
Authentication is handled by Keycloak 24 using the OpenID Connect (OIDC) protocol. The Next.js frontend redirects unauthenticated users to the Keycloak login page. After successful authentication, Keycloak issues a JWT access token that is stored in the browser and included in every API request.
Token Flow
- User accesses
/dashboard— Next.jsAppShelldetects no token inlocalStorage. - Redirect to
/loginpage. - User enters credentials — POST to Keycloak Token Endpoint.
- Keycloak returns
access_token(JWT, 15 min expiry) +refresh_token(7 days). - Frontend stores tokens — API client includes
Authorization: Bearer <token>. - Token refresh happens silently every 13 minutes.
JWT Payload (Example)
{
"sub": "a3f...uuid",
"preferred_username": "teacher@demo.myschool",
"realm_access": { "roles": ["teacher"] },
"tenant_id": "b7e...uuid",
"exp": 1723000000
}
Role-Based Access Control (RBAC)
Platform access is enforced at the API Gateway using Keycloak realm roles. Each role maps to a set of allowed endpoints and UI portal paths.
Role Definitions
| Role | Portal Path | Key Permissions |
|---|---|---|
| super_admin | /app/superadmin | Full platform access, tenant management, billing |
| school_owner | /app/schoolowner | School config, staff hiring, financial reports |
| principal | /app/principal | Academic management, timetables, staff oversight |
| teacher | /app/teacher | Attendance entry, grade submission, LMS content |
| student | /app/student | View attendance, grades, fees, LMS courses |
| parent | /app/parent | Child's attendance, fee payment, notifications |
| accountant | /app/finance | Full finance module, fee collection, payroll |
PostgreSQL Schema
All services share a single PostgreSQL cluster but use isolated schemas per domain. Every table includes tenant_id UUID NOT NULL as a row-level isolation key.
Primary Tables
| Table | Schema | Purpose |
|---|---|---|
tenants | public | School/institution registry |
students | academics | Student enrollment records |
courses | academics | Subject and course catalogue |
attendance_records | attendance | Daily attendance per student |
fee_invoices | finance | Fee invoices and payment status |
staff | hrms | Employee master records |
lms_courses | lms | Online course content |
outbox_events | public | Kafka outbox relay queue |
Alembic Migrations
# Apply all pending migrations
alembic upgrade head
# Roll back one migration
alembic downgrade -1
# Roll back to specific revision
alembic downgrade abc123def456
# Generate a new migration from model changes
alembic revision --autogenerate -m "add_student_gpa_column"
# Check current revision
alembic current
# View migration history
alembic history --verbose
alembic downgrade on a live database without a full backup. Always test migrations on a staging environment first.Backup & Restore
Automated Backups
Production databases use AWS RDS with automatic daily backups retained for 30 days. Point-in-time recovery (PITR) is enabled.
Manual Backup
# Full database dump
pg_dump -h localhost -U myschool_user -d myschool_prod \
--format=custom --compress=9 \
-f backup_$(date +%Y%m%d_%H%M%S).dump
# Upload to S3
aws s3 cp backup_*.dump s3://myschool-backups/postgres/ \
--sse aws:kms
Restore Procedure
# 1. Download backup from S3
aws s3 cp s3://myschool-backups/postgres/backup_20260808.dump .
# 2. Stop application services
docker compose stop app
# 3. Restore database
pg_restore -h localhost -U myschool_user -d myschool_prod \
--clean --if-exists backup_20260808.dump
# 4. Restart services
docker compose start app
REST API Reference
Required Headers
Authorization: Bearer <access_token>
X-Tenant-ID: <tenant_uuid>
Content-Type: application/json
SDK & Code Snippets
curl -X GET "https://api.myschoolos.com/v1/academics/students" \
-H "Authorization: Bearer <access_token>" \
-H "X-Tenant-ID: <tenant_uuid>"
Academics Endpoints
| Method | Endpoint | Description | Roles |
|---|---|---|---|
| GET | /academics/students | List students | admin, teacher |
| POST | /academics/students | Enroll student | admin |
| GET | /academics/courses | List courses | all |
| POST | /academics/attendance | Record attendance | teacher |
🧪 Interactive API Request Playground
GET https://api.myschoolos.com/v1/academics/students?limit=1// Click "Run Sample" to execute live mock payload
Finance Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /finance/invoices | Create fee invoice |
| GET | /finance/invoices/{id} | Get invoice details |
| POST | /finance/payments/razorpay | Initiate Razorpay payment |
| POST | /finance/payments/webhook | Razorpay webhook handler |
GraphQL Gateway
The GraphQL gateway aggregates data from all microservices into a unified schema. Use it for complex multi-entity queries that would require multiple REST calls.
# Example: Fetch student profile with attendance summary
query StudentDashboard($studentId: ID!) {
student(id: $studentId) {
id
fullName
rollNumber
attendanceSummary {
presentDays
absentDays
percentage
}
feeStatus {
totalDue
totalPaid
pendingAmount
}
currentGPA
}
}
⚡ Interactive GraphQL Query Playground
// Click "Execute GraphQL Query" to see live schema result
Docker Setup
Development Stack
# Start full development environment
docker compose -f docker-compose.dev.yml up -d
# Services started:
# - postgres:16 → localhost:5432
# - redis:7 → localhost:6379
# - kafka:3.6 → localhost:9092
# - zookeeper → localhost:2181
# - keycloak:24 → localhost:8080
# - mailhog → localhost:1025 (SMTP) / 8025 (UI)
Production Build
# Build all service images
docker compose -f docker-compose.prod.yml build
# Deploy with rolling update
docker compose -f docker-compose.prod.yml up -d --no-downtime
# Scale a specific service
docker compose up -d --scale academic-service=3
AWS Infrastructure
Architecture Components
| AWS Service | Purpose |
|---|---|
| ECS Fargate | Serverless container orchestration for all microservices |
| RDS PostgreSQL | Multi-AZ managed database with automated backups |
| ElastiCache Redis | Session cache and API response caching |
| Amazon MSK | Managed Kafka for event-driven outbox messaging |
| ALB | Application Load Balancer for service routing |
| S3 | File storage, database backups, exported reports |
| CloudFront | CDN for static frontend assets |
| Route 53 | DNS management and health checks |
| ACM | Free SSL/TLS certificate management |
CI/CD Pipeline
# .github/workflows/deploy.yml (overview)
on:
push:
branches: [main]
jobs:
test:
- npm run typecheck
- pytest services/ --cov
- npx playwright test
build:
- docker build + push to ECR
deploy:
- aws ecs update-service (rolling deploy)
- alembic upgrade head (migrations)
- Netlify deploy (frontend)
Deployment Environments
| Environment | Branch | URL |
|---|---|---|
| Development | main | localhost |
| Staging | staging | staging.myschoolos.com |
| Production | main (tagged) | app.myschoolos.com |
School Administrator Guide
Daily Operations
- Dashboard: Navigate to
/app/principalafter login to view the school overview dashboard. - Attendance Review: Go to Attendance → Today's Summary to see real-time class-wise attendance percentages.
- Timetable Management: Use Academics → Timetables to create and edit period schedules for each class.
- Academic Calendar: Set term dates, exam schedules, and holidays in Academics → Calendar.
Student Management
- Enroll new students via Admissions → New Application.
- Transfer or withdraw students in Academics → Students → Actions.
- Generate TC (Transfer Certificate) from the student record page.
Teacher Guide
Marking Attendance
- Log in and navigate to Attendance → Mark Today.
- Select your class and subject from the dropdown.
- Click each student's name to toggle Present/Absent.
- Click Submit Attendance — parents are automatically notified via WhatsApp for absent students.
Entering Grades
- Navigate to Examinations → Grade Entry.
- Select the exam, class, and subject.
- Enter marks for each student in the grid.
- Click Save Grades — GPA is calculated automatically.
LMS Course Management
- Create assignments in LMS → My Courses → Assignments → Add.
- Upload study materials (PDF, video link) in the Course Content section.
- Review student submissions and enter scores.
Student Guide
Accessing Your Dashboard
Log in at educationos-app.netlify.app/login with your student credentials provided by your school. Your dashboard shows attendance summary, pending fees, upcoming exams, and recent grades.
Viewing Attendance
Go to Attendance → My Record to view your monthly attendance chart and identify any days marked absent.
Fee Payment
- Navigate to Finance → My Fees.
- Click on a pending invoice.
- Click Pay Now — you'll be directed to the Razorpay payment page.
- A PDF receipt is sent to your registered email and parent's WhatsApp automatically.
Parent Guide
Mobile App Setup
- Download MySchool OS Parent App from Google Play Store or Apple App Store.
- Enter your registered mobile number and OTP to sign in.
- If you have multiple children, switch between them using the profile selector.
What You Can Do
- ✅ View daily attendance in real time
- ✅ Receive push notifications for absences immediately
- ✅ Pay school fees via UPI, card, or net banking
- ✅ Download fee receipts as PDF
- ✅ View term report cards and exam results
- ✅ Read school announcements and circulars
- ✅ Track child's school bus location (GPS)
School Owner Guide
Executive Dashboard
Log in at /app/schoolowner to access the School Owner Executive Dashboard with real-time KPIs:
- Total enrolled students vs. capacity
- Monthly fee collection vs. outstanding
- Attendance rate school-wide
- Staff payroll summary
- New admissions pipeline funnel
Financial Reports
Navigate to Finance → Reports to download:
- Monthly Collection Report (PDF)
- Outstanding Fee Arrears Report
- Term-wise Income Statement
- Scholarship Disbursement Summary
Troubleshooting
Login / Auth Issues
| Symptom | Cause | Solution |
|---|---|---|
| "401 Unauthorized" on all API calls | Access token expired | Clear localStorage and log in again; check token refresh interval |
Redirect loop on /login | Missing KEYCLOAK_URL env var | Verify .env has correct Keycloak URL and realm |
| Role not recognized | Missing Keycloak realm role | Assign correct role in Keycloak Admin Console → Users → Role Mappings |
Database Issues
| Symptom | Solution |
|---|---|
Migration lock error on alembic upgrade | Run SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' |
| Connection pool exhausted | Increase pool_size in SQLAlchemy settings; check for unclosed sessions |
Build Issues
# Next.js build fails with TypeScript errors
npm run typecheck --workspace=apps/web # Check errors
# The project has ignoreBuildErrors: true for production builds
# npm install fails in monorepo
rm -rf node_modules package-lock.json
npm install # Fresh install
Developer FAQ
How do I add a new microservice?
Copy the services/template-service/ folder, rename it, add it to docker-compose.yml, create an Alembic migration for its schema, and register its routes in the API Gateway router.
Can I use the REST API without the frontend?
Yes. All endpoints are available at https://api.myschoolos.com/v1/ with a valid Bearer token and X-Tenant-ID header. The Swagger UI is available at /docs.
How do I reset the development database?
docker compose stop postgres
docker volume rm myschool_postgres_data
docker compose up -d postgres
alembic upgrade head
npm run seed
How do webhooks work for Razorpay payments?
Configure your Razorpay webhook to POST to /finance/payments/webhook. The service verifies the signature using your RAZORPAY_WEBHOOK_SECRET env var and marks the invoice as paid.
Release Notes
v1.0.0 — August 2026 Current
Initial Commercial Release
- 15 fully implemented domain modules
- 7 role-based portals with Keycloak OIDC
- Razorpay + Stripe payment gateway integration
- Twilio WhatsApp + SMS notification hub
- React Native Expo mobile apps (Android + iOS)
- Kafka Transactional Outbox pattern
- Alembic database migrations
- Playwright E2E test suite
- AWS ECS + RDS production infrastructure
- Next.js 14 App Router frontend with Tailwind CSS