Essay · Money & Trust

Every Naira Must Land Somewhere

School fees look like the easiest part of school software. A parent owes an amount; the parent pays it; the system marks it paid. Every payment tutorial on the internet is built on that story: a checkout page, a reference number, a webhook that confirms the reference. Tidy.

Nigerian school fees do not work like that, and the gap between the tutorial and the reality is where a bursary quietly loses its credibility. I spent months rebuilding how our schools handle money — fees, transport, the bookshop — and the hardest problems had nothing to do with payment providers. They had to do with how families actually pay.

The reference is noise

Parents pay by bank transfer, at night, from whatever app their bank gave them. The reference that arrives is a thirty-digit string the bank invented. It means nothing to us, it is sometimes reused, and no parent has ever typed one. You cannot match money on references here. You have to match it on the money itself — the amount, the account it landed on, the family it plausibly belongs to, and the months it exactly covers.

That word exactly carries more weight than any other design decision. A payment that almost matches an invoice is not a match; it is a question for a human. "Close enough" is how one child's transport money becomes another child's tuition, and unwinding that costs more trust than the automation ever saved.

A family is a payment unit

The database thinks in students. Parents think in households. A mother with three children on the school bus sends one transfer for all three, for the whole term, in one bank alert. Whose invoice is that?

Our first matcher keyed families on the mother's phone number, and it worked until a father paid for two children whose forms carried his number in a different field. The money sat unmatched for days while he understandably asked what kind of school loses a transfer. The fix was humble: treat any shared parent phone number — any of the four fields a Nigerian enrolment form accumulates, with and without the +234 — as family. Data modelling here means modelling how families fill forms, not how the schema wishes they would.

And families pay in instalments that match nothing. Transport is a fixed amount per month; a parent sends part of it this week and the balance next week. Neither payment fits an invoice. Both together fit two months exactly. Software that only understands one-payment-one-invoice parks both and generates a phone call. Software built for this place accumulates the pieces and settles them the moment they exactly cover whole months.

Silence is the expensive failure

The worst bug I found in our old system was not a wrong number. It was a code path that, when a database write failed, told the payment provider "received, thank you" — and recorded nothing. The provider, satisfied, never retried. The money existed at the bank and nowhere else. Nobody stole anything. The system simply shrugged, and half a million naira became invisible until a deliberate audit dug it out of raw logs.

That is the failure mode that actually erodes a school: not fraud, but ambiguity. A parent who paid and is still marked owing does not care that the bug was subtle. From that day the design rule in our system is absolute: every naira must land somewhere visible. If the software cannot classify a payment, it goes to a suspense account — on a dashboard, with an ageing timer — never into a void.

Balances are opinions; ledgers are facts

For months my real job title was reconciler-in-chief. Transport money leaked into tuition. Wallet balances disagreed with their own histories. Every fix was correct, and every fix was another patch on the same disease: the system had many tables that each held an opinion about the money, maintained by dozens of functions, and nothing that held the fact.

The cure turned out to be seven hundred years old. Double-entry bookkeeping, enforced by the database itself: every movement of money is a balanced transaction between accounts, the books must sum to zero or the write is refused, and nothing is ever edited or deleted — corrections are reversing entries made in the open. Fees, transport and bookshop money live behind purpose walls, so one stream structurally cannot pay for another. It is not glamorous. It is the difference between a number you defend and a number that defends itself.

We did not flip a switch, either. The new ledger ran in shadow for weeks — mirroring every write of the old system, backfilled with a full year of verified history, compared against the old numbers every night — before anything depended on it. When the subject is other people's money, a migration you cannot quietly rehearse is a gamble you are taking with someone else's children's school fees.

The system must police its author

The part I trust most is not the ledger. It is the watchdog around it: hourly checks that every balance equals the sum of its entries, that no money is both settled and still unclassified, that nothing was allocated beyond what actually arrived. Broken maths heals itself; genuine conflicts message my phone, because in Nigeria operational truth lives on WhatsApp, not in an unread email.

Within the first hour of those checks existing, one of them fired — and the person it caught was me. A sequencing mistake in my own migration had counted six payments twice. The alert did not know or care that the author of the mistake was the author of the system. That is exactly the point. Integrity checks are not for catching bad people; they are for catching everyone, including the two-in-the-morning version of yourself doing emergency surgery on production.

The goal was never accounting elegance. It was believability: that a parent, a bursar, and I can look at the same number and none of us needs faith. Money people believe is money that is complete, traceable, separated, self-checking, and corrected in the open. Everything else is a balance somebody is hoping about.

Next term, some parent will send one transfer for three children at nine in the evening, with a reference that means nothing. It will land, be classified, matched to the family, and settled to the kobo. And if it can't be, it will not disappear. It will sit in suspense, visibly, with an alert on my phone — because the first promise a school's money system makes is that every naira lands somewhere.

Joan Urevbu is an education-technology builder and writer working between Benin City, Nigeria and Porto Alegre, Brazil. She writes about building software for schools, designing for low-bandwidth realities, and institutional trust. Reach her at admin@upsshub.com.
← Why I Don't Build the School Chatbot Everyone Asks For All essays