Back to all cases
Education Operations2026

Anonymized Case — Operations System for a 3-Campus Tutoring School: scheduling, attendance, package burn-down, and payroll on one chain

Replacing a per-seat SaaS scheduler with a custom operations system for a three-campus tutoring chain — attendance is the single source of truth, and package burn-down, invoices, and teacher hours are all derived from it.

A custom operations system for a three-campus tutoring chain, replacing a per-seat SaaS: student and family records, course catalog, recurring scheduling with conflict detection, attendance tracking, tuition packages/invoices/payments — with teacher hours pushed automatically to an employee-management system for payroll over versioned APIs. Client identity anonymized.

A tutoring school's operational pain is never 'one missing feature' — it's a broken data chain: scheduling in one system, attendance in spreadsheets, package reconciliation by hand, teacher hours re-tallied at month-end. Every link can fail, and every month repeats the same labor. The school's previous overseas SaaS charged per seat, didn't fit local workflows, and wouldn't let the data out. We built them a custom operations system with one core design decision: attendance is the single source of truth, and everything else is derived from it.

Privacy note: institution name and student information have been removed. Only architecture, workflow, and delivered outcomes are described.

3 campuses
Unified operations
Attendance
Single source of truth
API push
Hours → payroll

The challenge

Three campuses shared a per-seat SaaS scheduler: recurring classes collided, attendance never matched package burn-down, package balances were maintained by hand, and teacher hours were tallied manually at month-end. More campuses meant more reconciliation and harder-to-trace errors.

Our approach

Rebuild the data chain around attendance as the source of truth. Student and family records, the course catalog, and recurring scheduling (with three-way conflict detection across teacher, room, and student) sit upstream. Once a class's attendance is confirmed, it automatically drives everything downstream: package deduction, invoice generation, payment reconciliation, and teacher-hour accumulation. Teacher hours are no longer tallied by hand — they push automatically over versioned APIs into the employee-management system we built for the same client group, feeding payroll. The system ships as modules, with unified data and per-campus permission isolation.

Results

Three campuses now operate in one system: scheduling conflicts are blocked at creation time; once attendance is confirmed, burn-down, balances, and invoices update automatically — month-end manual reconciliation is gone; teacher hours accumulate in real time and flow straight into payroll. The school is off the per-seat SaaS and owns its data outright.

Attendance as the single source of truth

Every flow of money and time in the system derives from attendance records:

  • Attendance confirmed → package hours deduct automatically, balances visible in real time.
  • Attendance accumulates → invoices generate from actual classes consumed; every line a parent sees is backed by an attendance record.
  • Attendance is hours → teacher pay accumulates from confirmed attendance, no month-end tally.
  • Attendance edits leave a trail → every backfill or correction is logged, so reconciliation is traceable.

This eliminates 'which number is right' by design: attendance is the only thing entered — everything else is computed.

Recurring scheduling with three-way conflict detection

Tutoring scheduling is hard because it recurs: a course runs the same slot for 20 weeks, and mid-term room changes, teacher swaps, and student transfers are routine. The system checks conflicts across teacher, room, and student dimensions at create and edit time — collisions surface before saving, not on the first day of class.

Hours straight to payroll: a versioned handshake between two systems

Teachers generate hours in the operations system and get paid in the employee-management system. The two talk over versioned APIs: the operations side pushes hours from confirmed attendance, and the payroll side receives with idempotency and version checks — retries never double-pay, and interface evolution never breaks reconciliation.

  • Idempotent pushes: the same class's hours can't be booked twice by a retry.
  • Versioned interfaces: either side can upgrade without breaking the other's reconciliation.
  • The employee-management system is our own standalone product (12 toggleable modules: time clock, time off, reviews, tasks, commission, payroll, and more).

Technical breakdown

  • Python (Flask) backend + PostgreSQL + Redis task queue, Next.js frontend, deployed with Docker Compose.
  • Shares one platform architecture with the CRM and employee-management products for the same client group — deliberately copied, not shared-library-coupled, so each product evolves independently.
  • Modular delivery: records, scheduling, attendance, packages, and invoicing/payments are independent modules, enabled as needed.
  • One database across three campuses with per-campus permission isolation; cross-campus reporting works out of the box.

Reusable lessons

  • The first design decision of an operations system is choosing the single source of truth. Choose wrong (or not at all) and everything downstream becomes reconciliation.
  • Replacing SaaS isn't just saving subscription fees — it's owning the data and fitting local workflow, which will never be an overseas SaaS vendor's priority.
  • Cross-system money interfaces must be idempotent and versioned, or every retry and upgrade is a financial incident.

Want results like these?

Tell us about your business and we'll scope a proof of concept.

More case studies