Back to work
Case study · PT Trikala Solusi Indonesia

Sekolah Unggul

A multi-tenant school ecosystem I founded and build end to end — with a CBT exam engine that sustains ~290 students testing simultaneously with data consistency and zero downtime.

Client
PT Trikala Solusi Indonesia
Year
2026 — Present
Role
Founder
Stack
Node.jsRustMongoDBPostgreSQLRedisGCP Cloud RunCloudflare WorkersFlutterESP32 / RFID

The Challenge

Schools don't need another single-purpose app — they need one ecosystem that runs the academic day: exams, library, assignments, parent visibility, and attendance.

The hardest engineering problem hides in one feature: computer-based testing. Exam load is not gradual — hundreds of students press "start" within the same minute, every answer must be persisted consistently, and downtime in the middle of an exam is not an inconvenience, it's a failed exam for an entire school.

The Platform

Sekolah Unggul is a multi-tenant school ecosystem serving ~500 paying students across 3 schools, plus a freemium cohort under conversion:

  • CBT exams built for bursty concurrent load
  • Library, assignments, and gamification for daily learning
  • Parent monitoring for visibility into student activity
  • RFID attendance on custom ESP32 hardware I designed and deployed
  • School-fee (SPP) billing — hosted payments via a payment gateway, with disbursements to school accounts
  • Cashless canteen wallet — currently in development, built as its own Rust service

Engineering the Exam Burst

The CBT engine is designed around the burst, not the average. During exam windows it sustains ~290 students testing simultaneously — with data consistency and no downtime.

How it holds:

  • Redis for hot exam state: answers and session state land on a fast path first, keeping writes consistent under simultaneous load
  • Auto-scaling GCP Cloud Run: capacity follows the burst — scaled out for the exam window, scaled down after, so cost tracks actual usage
  • Designed for load before it arrives: the exam window is a known, scheduled spike — the architecture treats it as the primary design case, not an edge case

System Architecture

The exam burst shaped the compute; the money flows shaped the data model. Sekolah Unggul isn't one application — it's three backend services with deliberately different languages, databases, and guarantees:

System.map — one platform, three backends
Clients & devices
Flutter app · students · teachers · parents React web apps · one per role ESP32 RFID devices · attendance Canteen cashier & kiosk · in development
Services — polyglot by workload
backend-core · Node/Express — auth, academic, LMS payment-backend · Node — school-fee billing kantin-pay · Rust/Axum — canteen wallet · in development
Data — money split from operations
PostgreSQL · money — ACID source of truth MongoDB · school data + bills Redis · cache · sessions · QR anti-replay
Runtime & integrations
GCP Cloud Run · asia-southeast2 · auto-scaling Cloudflare Workers · web frontends at the edge Finpay / Finnet · payment gateway
Money lives in PostgreSQL (ACID source of truth); operational school data lives in MongoDB — a deliberate split, kept in sync with idempotent HMAC-signed webhooks because the payment gateway retries without idempotency guarantees.

The decisions that matter:

  • Money is separated from data: wallets, balances, and gateway transactions live in PostgreSQL with ACID transactions; flexible school data lives in MongoDB. The two stay in sync through idempotent webhooks — the payment gateway retries callbacks without idempotency guarantees, so exactly-once is enforced internally.
  • The hot canteen path is being built in Rust (in development): HMAC-signed QR codes with Redis anti-replay, Argon2-hashed PINs, and atomic debit/credit — designed for a cashier line, not a batch job.
  • Serverless-first runtime: core services auto-scale on Cloud Run (Jakarta region) and scale to zero when idle; web frontends ship from Cloudflare's edge. No cluster to babysit.

Following the Money — SPP Billing

Payments are where multi-store consistency gets real. This is the path a school-fee payment takes from a parent's phone to the school's balance:

Flow.map — how a school-fee payment lands
Parent — mobile app
Opens the bill · read from MongoDB
Payment gateway — hosted page
VA · cards · e-wallets Pending transaction recorded · PostgreSQL
Signed webhook lands
HMAC-verified callback · retried by the gateway — must be safe to repeat
Money settles — PostgreSQL
School balance credited Finance history written
Bill flips to paid — MongoDB
Status: paid · safe under duplicate callbacks Push notification to the parent
The gateway retries callbacks and does not guarantee idempotency — so the "paid" flip is idempotent and every money write happens inside one ACID transaction.

Owning the Whole Stack

As founder, I own everything end to end: the backend, the cloud infrastructure, and the custom RFID attendance hardware on ESP32. It's the same operating model I ran as CTO — stay close enough to the code to make the hard calls myself — applied to a company of my own.

Where It Stands

~290
Concurrent exams sustained, zero downtime
~500
Paying students
3
Schools, plus a freemium cohort under conversion

This isn't a retrospective — the system this page describes is serving schools right now. Here's the backend responding live:

Live.status — backend-core
service · Sekolah Unggul API — GCP Cloud Run, asia-southeast2
status · checking live…

What I'd Do Differently

Designing for the exam burst from day one was the right call. What I'd start earlier is the commercial side: instrumenting freemium-to-paying conversion alongside the product, instead of treating revenue signals as something to wire up after the engineering is done.

goto esc