Technical Specification · Audience: Technical Marketers

Shule / my‑school

A multi-tenant school management platform built for East African K-12 institutions, covering academics, finance, HR, safeguarding, and parent engagement in a single integrated system.

Version 2.0
Date July 2026
Services 14 microservices
Stack FastAPI · Next.js 15 · PostgreSQL
Markets Kenya · Tanzania · Uganda
Platform Overview

What is Shule?

Shule (Swahili: school) is a vertically integrated school management system designed specifically for East African K-12 schools, covering the full operational lifecycle from student admissions to leaving certificate generation. It runs as a SaaS platform on my-school.co.ke, with each customer school receiving an isolated tenant environment.

The platform replaces fragmented point solutions (separate fee-collection apps, paper registers, SMS-only parent communication, spreadsheet timetables) with a unified system where student records, academic results, attendance, fees, HR, and communications share a single source of truth. Events flow between modules: an absence automatically triggers a parent SMS; a fee payment updates a student's ledger and the bursar's dashboard simultaneously; a published report card queues PDF delivery to all guardians.

Market positioning

Designed for the Kenyan CBC and 8-4-4 curriculum frameworks
KEMIS, TZ-EMIS, and UG-EMIS statutory reporting built in
M-Pesa Daraja C2B and STK Push as first-class payment rails
Multi-currency support (KES, TZS, UGX, USD)
Airtel Money, MTN MoMo, Flutterwave, and AzamPay (TZ) integrated
Swahili-aware UI with a translate helper covering 190+ languages
Offline-capable mobile attendance and gradebook (PWA + queue)
Chain / multi-school network dashboard for school groups

Key differentiators vs. generic SIS products

CapabilityGeneric SISShule
East African payment railsNot availableM-Pesa, Airtel, MTN, Flutterwave, AzamPay
Government reportingManual exportKEMIS, TZ-EMIS, UG-EMIS auto-population
CBC curriculumNot applicableStrand/sub-strand assessments, competency bands, CBC report card
Multi-tenant isolationRow-level taggingDedicated PostgreSQL schema per school
Timetable solverManual gridConstructive + simulated annealing, TSC constraint validation
SafeguardingNoneCP case management, DSL workflow, SEND/IEP, wellbeing tracking
ZKTeco biometricNot availableZKTeco terminal integration for automated attendance
Architecture

System design

Shule is a microservices system: 14 independent FastAPI services, each owning a bounded domain, communicating via NATS JetStream for async events and a PostgreSQL-backed outbox for guaranteed delivery. A Next.js 15 frontend and an Expo mobile app consume the services through a typed API layer.

Client tier
Next.js 15 Web (my-school.co.ke)
Expo Mobile (iOS / Android)
USSD (*384#)
REST API consumers
LTI 1.3 platforms
↓ HTTPS / Caddy reverse proxy (TLS termination, subdomain routing)
API gateway + auth
Keycloak OIDC (auth.lindela.io)
JWT validation middleware (shule-auth lib)
Tenant context middleware
Service layer — FastAPI microservices
core
academic
attendance
comms
fees
safeguarding
library
facilities
hr
ai
video
sports
reports
integrations
Messaging & async
NATS JetStream (events + outbox relay)
Temporal worker (scheduler service)
Event outbox per tenant schema
Data tier
PostgreSQL primary (db.lindela.io)
PG 17 hot standby
MinIO S3-compatible (PDFs, uploads)
Redis (sessions, USSD state)
Supporting services
LiteLLM (AI proxy — ml.lindela.io)
OpenBao (secrets management)
Stalwart SMTP
Prometheus + Grafana + Loki

Multi-tenancy model

Each school is a completely isolated PostgreSQL schema named t_{tenant_slug}. This is schema-per-tenant isolation: stronger than row-level filtering and weaker than a separate database. Every table for a school's data lives in that schema; migrations run against all tenant schemas in sequence, guarded to be idempotent.

Why schema-per-tenant? It allows a single PostgreSQL cluster to host hundreds of schools while guaranteeing that a query in one school's context cannot access another school's data, even through ORM bugs or injection. Row-level security is a single policy failure away from cross-tenant leaks; schema isolation requires deliberate misconfiguration to break.

The platform schema shule_system holds the tenant registry, billing records, platform audit log, and operator CRM. The Caddy reverse proxy reads the subdomain (demo.my-school.co.ke) and passes the tenant slug as an HTTP header; the TenantSession dependency in each service resolves this header to the correct schema for every query.

Technology stack

Python + asyncio FastAPI SQLAlchemy (async) Alembic migrations Pydantic Next.js 15 (App Router) TypeScript / React 19 TanStack Query Expo SDK PostgreSQL (asyncpg) NATS JetStream Keycloak (OIDC) MinIO (S3) Redis WeasyPrint (PDF rendering) Caddy (TLS + reverse proxy) Prometheus + Grafana Sentry (error tracking) uv (Python workspace manager) pnpm workspaces Docker (local dev)
Feature Modules

Service-by-service capabilities

Each service is a standalone FastAPI application with its own database models, business logic, and REST API. Services communicate synchronously via HTTP (internal calls) and asynchronously via NATS JetStream events published through a transactional outbox.

Core — Students, Staff & School Administration

The Core service is the system of record for every person in the school: students, guardians, and staff. It also owns school settings, calendar events, admissions, alumni tracking, recruitment, and the platform-level operator console.

Service
core
Systemd
shule@core
Student enrollment, profile management
Year group and form class assignment
Guardian linking and emergency contacts
Staff profiles, employment details
Admissions pipeline and offer management
Alumni tracking and leavers register
Bulk student & staff CSV/Excel import
Year-end promotion (individual + bulk)
School events calendar
Compliance calendar (statutory deadlines)
SEND register (initial needs capture)
Medical records and immunisation log
School branding and settings management
SSO configuration (OIDC/SAML)
Principal morning briefing dashboard
Duty rota management
Recruitment: vacancies, applications, onboarding
Network / chain performance dashboard
Data export: students CSV, staff CSV
Operator console (platform-level admin)

Academic — Timetable, Marks, Report Cards & Curriculum

The Academic service manages everything that happens in the classroom: timetable creation and publishing, grade books, CBC strand assessments, homework, lesson plans, exams, subject choices, and report card generation.

Service
academic

Timetable engine

The solver uses a constructive + simulated-annealing algorithm, deterministic by seed. It consumes teacher availability constraints, subject requirements per class, room types, and double-period rules. Clash validation uses CP-SAT. TSC teaching-load constraints (maximum lessons per teacher) are enforced at publish time.

Version-controlled timetable drafts
Automated generation from curriculum requirements
Teacher-subject qualification matrix
Per-teacher max periods/day and unavailability
Double-period (block) lesson support
A/B week pattern support
Manual lesson move with live clash validation
Cover teacher suggestion and assignment
Lesson cloning across versions
Published timetable → attendance session scaffold

Marks, reports & CBC

Grade book entry (individual + bulk)
Custom grade boundaries per subject
Class and student performance analytics
Grade distribution and trend charts
Top performers and at-risk identification
Report card generation (PDF)
CBC strand/sub-strand assessments
CBC competency band tracking
CBC student and class summary reports
KCSE candidate registration (KNEC)
Exam seating plan and invigilator assign
Subject choices management
Academic trajectory per student
Cohort ranking and progress summary
Holiday and class homework management
Lesson plans with review workflow
Learning objectives and resources
Reading progress tracking
Parents' evening scheduling
AI-suggested report-card comments

Attendance — Register, Biometric & Analytics

Attendance supports daily, session-by-session, and bulk mark modes. It integrates with ZKTeco biometric terminals for automated capture, and triggers guardian notifications on absence detection through the comms service.

Service
attendance
Session-based attendance register
Bulk mark (full class in one action)
Assembly (whole-school) attendance
ZKTeco biometric terminal integration
Timetable-linked session auto-creation
Absence request and approval workflow
Attendance exemption management
Cover session management
Automatic session close (scheduled)
Guardian SMS on absence detection
Bulk attendance certificates (PDF)
Class summary and school-wide analytics
Student attendance history and trends
Teacher class-coverage metrics
Avoidance pattern analysis
Offline mark queue (PWA, syncs on reconnect)

Fees & Finance — Invoicing, Payments & Reporting

The most feature-dense service on the platform. Manages the complete school fee lifecycle: schedule creation, term invoice generation, payment collection across five payment rails, scholarship and bursary management, bank reconciliation, and statutory financial reporting.

Service
fees

Fee management

Fee schedules per year group and term
Custom fee structures (ad-hoc items)
Bulk term invoice generation
Instalment plan creation and tracking
Fee waivers and write-offs (audited)
Scholarships with disbursement tracking
Bursary schemes with application workflow
Government capitation tracker (MoE)
Void invoice with reversal audit trail
Daily cashbook and financial year summary
Budget vs. actual reporting
Close financial year with rollover

Payment rails

ProviderMethodMarketsNotes
Safaricom M-PesaDaraja C2B, STK Push, paybillKEPer-tenant paybill + passkey configuration
Airtel MoneyAPI collectionKE, TZ, UGCallback + status polling
MTN MoMoAPI collectionUG, otherOAuth 2 token management
FlutterwaveCard, bank, mobileMulti-countryInitiate + verify + webhook
AzamPayMobile moneyTZTanzania-specific rail
Bank transferStatement upload + reconciliationAllAuto-reconcile by reference number

Defaulter management & collections

Automated delinquency escalation ladder
Flag, escalate, and resolve fee defaulters
Bulk fee-reminder SMS via Africa's Talking
Per-school dunning stage configuration
Payment plan creation and monitoring
Pledge tracking (parent commitment records)
Fee receipt PDF generation
Expense claim and approval workflow

Procurement & bookshop

Acquisition request workflow
Bookshop inventory and uniform shop
External invoice management
Kenya payroll integration (PAYE, NSSF, NHIF, SHIF)

Human Resources

Full HR lifecycle management covering contracts, leave, payroll (Kenya), performance appraisal (TPAD and OPRAS), DBS/right-to-work compliance, CPD tracking, and cover request management.

Service
hr
Staff contracts (creation, amendment, termination)
Leave requests, balances, and review workflow
Kenya payroll: PAYE, NSSF, NHIF/SHIF
P9 certificates and P10 return export
TRA PAYE return (Tanzania)
Payslip generation (PDF)
TPAD appraisal (TSC Kenya): self-appraisal and appraiser review
OPRAS appraisal (Uganda equivalent)
KPI management with self/manager rating
Performance cycle lifecycle
Peer review workflow
CPD record and approval tracking
DBS check register and expiry alerts
Right-to-work documentation
Bradford factor (absence pattern analysis)
Vacancies, applications, and offer management
New-hire onboarding task checklist
SCR (Single Central Register) export
Staff expense claims and reimbursement
Cover assignment and substitution tracking

Communications

Unified multi-channel messaging: in-app threads, SMS via Africa's Talking, WhatsApp Business Cloud API, push notifications, and broadcast campaigns. Absence alerts are event-driven from the attendance service via NATS.

Service
comms
In-app messaging threads
SMS via Africa's Talking (bulk + direct)
WhatsApp Cloud API (text + media)
Push notifications (FCM)
Broadcast campaigns (scheduled / immediate)
Bulk message campaigns with delivery tracking
Absence alert automation (NATS consumer)
Fee reminder SMS with paybill reference
Per-guardian notification preferences
Per-school SMS/WhatsApp toggle
Twilio SMS webhook support
Dead-letter queue viewer and replay
Message delivery log
Report card publication guardian notification

Safeguarding, Behaviour & SEND

Sensitive-data module for child protection case management, DSL workflow, SEND/IEP records, behaviour incidents, wellbeing check-ins, and pastoral care. Access is role-gated to DSL and SENCO roles.

Service
safeguarding
Child protection (CP) case creation and tracking
Safeguarding incident reporting and status workflow
Anonymous concern submission
Disciplinary hearing scheduling and close
Behaviour incident log and resolution
Merit / demerit points system
SEND register (open, update, close)
Individual Education Plans (IEP)
SEN interventions with review dates
Wellbeing counselling caseload
Medical prescriptions and immunisation schedule
Student health overview

Library

Library catalogue management, loan tracking, MARC record import, reading progress tracking, and fine management.

Service
library
Book catalogue (add, search, update)
MARC record import
Loan checkout and return
Loan renewal and overdue notifications
Fine calculation and waiver
Reservation and collection queue
Reading progress per student
Class reading summary dashboard

Facilities, Assets & Visitors

Room bookings, asset register and tracking, maintenance request workflow, visitor sign-in/out, transport management, and health & safety checklists.

Service
facilities
Room booking and scheduling
Asset registration and lifecycle
Asset condemnation and disposal
Maintenance request and status tracking
Visitor sign-in / sign-out (digital)
Visitor history search
Transport routes and stops
Student transport enrollment
Locker assign and release
H&S checklist management
Canteen menu and item management
School vehicle fleet register

Sports & Co-curricular

Sports teams, fixtures, achievements, badges, and co-curricular clubs. Feeds into student portfolio for universities and employers.

Service
sports
Team creation and member management
Fixture scheduling and results recording
Achievement and merit awards
Achievement badge leaderboard
Student co-curricular portfolio
Activity and clubs register

Reports & Documents

WeasyPrint-based PDF generation for all formal school documents. All generated PDFs are stored in MinIO with a cryptographic verification token; any printed document can be verified online via /verify/{token}/{tenant}.

Service
reports
Report cards (standard + CBC formats)
Student clearance certificates
Leaving certificates
Student ID cards (individual + A4 sheet)
School poster generation
Fee receipts and payment summaries
Payslips and P9 certificates
Custom report definitions (column-builder)
CSV and PDF export for any report
HMAC-signed verification QR on every document
Public document authenticity verification endpoint
Presigned MinIO URLs with permanent key storage
Document verification: Every PDF issued by the platform carries a QR code linking to https://my-school.co.ke/verify/{token}/{tenant}. The token is HMAC-SHA256 signed with a serial number, document type, and document ID. Third parties (universities, employers) can verify document authenticity without contacting the school.

Scheduler & Workflow Automation

A Temporal worker service manages all time-based and event-driven workflows: automated attendance session creation, fee dunning, cover assignment, timetable scaffolding, and overdue notifications.

Daily timetable → attendance session scaffold
Automatic session close after school hours
Fee reminder cascade (3-day, due, +7d, +14d)
Subscription dunning state machine
Overdue loan and fine notifications
DBS / right-to-work expiry alerts
Monthly student-count metering for billing
User Experience

Portals by role

The Next.js 15 frontend routes users into distinct portal experiences based on their Keycloak role. All portals share a single deployment: the subdomain identifies the school, and the role determines the navigation tree and accessible pages.

PortalRoleRoute prefixKey pages
Admin / Staff shule-admin, shule-head-teacher, shule-bursar, shule-support (dashboard)/ Dashboard, students, academic, attendance, fees, HR, comms, safeguarding, library, facilities, sports, reports, AI analytics, settings
Teacher shule-teacher (teacher)/teacher/ Today's timetable, gradebook, homework, lesson plans, attendance, cover sessions, resources
Parent / Guardian shule-parent, shule-guardian (parent)/parent/ Child profile, fees, grades, attendance, timetable, homework, report card, messages, notices, consent, goals, achievements, parent-teacher meetings, events
Student shule-student (student)/student/ Timetable, grades, homework, report card, attendance, achievements, resources, portfolio, messages
Platform Admin shule-super-admin (dashboard)/platform/ Tenant management, billing, system audit log, announcements, support tickets, event/outbox viewer

Mobile app (Expo)

The Expo mobile app (iOS and Android) mirrors the teacher and parent portals, with offline capability for attendance marking and gradebook entry. Marks queued offline sync automatically when connectivity is restored.

USSD access

Fee balance enquiry and payment status are accessible via USSD short code (*384# pattern) using Redis-backed session state, enabling parents with feature phones to check balances without the web app.

AI & Analytics

Predictive intelligence

The AI service routes to LiteLLM (self-hosted on , proxying Claude/GPT/Llama based on configuration). AI features are additive; the platform operates fully without them if the LiteLLM endpoint is unreachable.

At-risk student scoring (composite: attendance, grades, fees, behaviour)
Early-warning dashboard with per-factor breakdown
Enrolment forecast (linear projection from historical data)
Dropout risk trend analysis
Equity analysis across demographic cohorts
AI-suggested report-card comments (teacher editable before save)
Student academic trajectory modelling
Performance alert detection and acknowledgement
Workload analysis per teacher
Privacy posture: LLM calls for report-card comment suggestions pass only marks, subject name, and attendance summary. No personally identifiable information is included. The teacher sees the suggestion and must edit before submission; nothing is auto-published from AI output.
Integrations

External systems & standards

Government education management systems

SystemCountryCapability
KEMISKenyaLearner registration, term enrolment return, monthly attendance summary, CSV export
TZ-EMISTanzaniaEnrolment records, upsert and CSV export
UG-EMISUgandaEnrolment records, upsert and CSV export
KNECKenyaKCSE candidate registration, bulk register, confirmation
Ed-FiStandardStudents, staff, and school-association REST endpoints

EdTech standards

LTI 1.3: platform registration, OIDC login, launch callback, JWKS endpoint
OneRoster: orgs, users, and enrolments endpoints
SCIM 2.0: user provisioning / deprovisioning, token management
xAPI (Experience API): learning activity statement store and query

Webhooks & event delivery

Schools can register outbound webhooks for any NATS event type. The delivery subsystem retries failed deliveries, maintains a delivery log with per-attempt status, and exposes a retry endpoint for manual replay.

API access

All service APIs follow REST conventions with JSON request/response bodies, UUIDv7 identifiers, and ISO 8601 timestamps. Authentication uses OAuth 2 Bearer tokens issued by Keycloak. Each service exposes OpenAPI docs at /docs (non-production environments). Rate limiting is handled at the Caddy layer.

Security & Compliance

Security architecture

Authentication & authorisation

Keycloak OIDC (JWTs, refresh tokens)
RS256-signed tokens, JWKS auto-rotation
Per-realm role-based access control (RBAC)
12 distinct roles with least-privilege enforcement
Per-tenant SSO (OIDC/SAML integration)
Tenant suspension enforcement (402 on all routes)

Data isolation

Schema-per-tenant PostgreSQL isolation
Tenant ID validated on every API request
System and tenant schemas are query-level separate
All S3/MinIO paths namespaced by tenant ID

Compliance features

System audit log (all operator actions)
Per-tenant fee and HR audit trail
DSAR (Data Subject Access Request) ZIP export
Parental consent records (guardian + student)
GDPR-aware video streaming (FRT disabled, DPIA tracking)
Document HMAC verification (anti-forgery)
Secrets in OpenBao (not plaintext in env)
CSP headers enforced at Caddy layer
Safeguarding data: CP case records, SEND files, and counselling notes are accessible only to users with the shule-dsl or shule-senco roles. No safeguarding data is included in DSAR exports to non-authorised requesters. Audit entries are written for every access.
Infrastructure

Hosting & deployment

The platform runs on a fleet of Contabo (EU) dedicated servers. The production app server is separate from the database host; a hot-standby replica runs continuously.

HostRoleKey services
App farm14 FastAPI services, Next.js, Caddy
DB primaryPostgreSQL, nightly pg_dump per schema, 30-day retention
DB hot standbyPG streaming replication, off-site backup rsync target
AuthKeycloak, SpiceDB, MinIO
ML / VaultLiteLLM , OpenBao, Ollama
ObservabilityStalwart SMTP, Prometheus, Grafana, Loki

Deployment model

14 systemd services (shule@*) managed by deploy-prod.sh
Next.js built locally, rsynced as standalone artifact (never built on server)
Zero-downtime deploys via systemd reload + health check
Alembic migrations run against all tenant schemas on every deploy
Smoke-check script validates all 16 systemd units post-deploy
Rollback to any prior git ref in under 3 minutes
Prometheus metrics endpoint on every service (/metrics)
Sentry error tracking (env-gated, both backend and frontend)

Observability

Every FastAPI service exposes Prometheus metrics at /metrics. Grafana () aggregates request rate, latency, error rate, and custom business metrics (invoice volume, attendance rates, NATS event lag). Loki collects structured JSON logs from all services. Sentry captures unhandled exceptions in both Python services and the Next.js frontend.

Technical Reference

Roles, ports & conventions

RBAC role reference

Keycloak rolePortalAccess level
shule-super-adminPlatform consoleCross-tenant operator access, billing, tenant management
shule-adminAdmin dashboardFull school administration, all modules
shule-head-teacherAdmin dashboardAcademic management, staff oversight, timetable
shule-teacherTeacher portalOwn classes, gradebook, attendance, lesson plans
shule-bursarAdmin dashboardFees, payments, payroll, procurement
shule-dslAdmin dashboardSafeguarding (CP cases, full access)
shule-sencoAdmin dashboardSEND register, IEPs, interventions
shule-librarianAdmin dashboardLibrary catalogue and loans
shule-supportAdmin dashboardRead-only support access across modules
shule-parentParent portalOwn children only: fees, results, communications
shule-guardianParent portalEquivalent to parent, alternative guardian relationship
shule-studentStudent portalOwn profile only: timetable, results, homework

Service port map

core
Students, staff, admissions, events, settings
academic
Timetable, marks, CBC, homework, exams
attendance
Sessions, registers, biometric, cover
comms
SMS, WhatsApp, push, broadcast
fees
Invoicing, payments, M-Pesa, bank recon
safeguarding
CP cases, behaviour, SEND, wellbeing
library
Catalogue, loans, fines, reading
facilities
Rooms, assets, maintenance, visitors
hr
Contracts, leave, payroll, appraisal, DBS
ai
At-risk scoring, forecasting, LLM comments
video
GDPR streaming, FRT disable, DPIA
sports
Teams, fixtures, achievements, clubs
reports
PDF gen, clearance certs, ID cards, verification
integrations
KEMIS, EMIS, LTI, SCIM, xAPI, webhooks, USSD

API conventions

Base path pattern: /api/v1/{service}/{resource}
All IDs are UUIDv7 strings (time-ordered, sortable)
Timestamps: ISO 8601 with timezone (2026-07-24T10:30:00+03:00)
Error responses: {"error": "ERROR_CODE", "message": "..."}
Pagination: ?page=1&page_size=50, response includes total
Auth header: Authorization: Bearer {keycloak_access_token}
Tenant scope: resolved from subdomain via X-Tenant-ID header
OpenAPI docs at /docs (non-production) and /openapi.json

Event subjects (NATS)

Subject patternTrigger
shule.fees.invoice_createdTerm invoice generated
shule.fees.payment_receivedM-Pesa / bank payment matched
shule.attendance.absence_detectedStudent marked absent in session
shule.academic.report_card_publishedTerm report card published to portal
shule.core.student_enrolledNew student accepted and enrolled
shule.academic.timetable_publishedNew timetable version made live

Consumer services subscribe to relevant subject patterns. Failed deliveries land in shule.dlq.* subjects, visible and replayable via the platform console.