AG

Case study · Mobile-money collections

One Acre Fund: farmer repayments on M-Pesa, checked before money moves

By · Published · Updated

One Acre Fund lends seed and fertiliser to smallholder farmers and collects repayment in small M-Pesa instalments. I was lead architect on the payment hub that took those repayments direct to M-Pesa, checked each one against the loan ledger first, and ran in One Acre Fund's own cloud from 2022 to 2024.

Client
One Acre Fund, Kenya
Delivered through
Fynarfin, with the Mifos Initiative
When
2021 – 2024
My role
Lead architect: deployment, connectors, production operations and payouts scoping
Stack
Mifos Payment Hub EE, Safaricom M-Pesa, Zeebe, Kafka, Elasticsearch, Helm on Kubernetes
Team
Eight Fynarfin engineers, with One Acre Fund's business owner and engineers
Outcome
Live from February 2022; about 1.2 million repayments a month direct to M-Pesa; one Helm chart One Acre Fund runs itself

The problem

One Acre Fund (OAF) lends in kind. Farmers get certified seed and fertiliser at planting time and repay in many small payments before harvest, and in Kenya almost all of that money arrives over M-Pesa. At OAF's scale, small problems per transaction become large sums: a fee that's slightly too high, a payment credited to the wrong account, a repayment that never reaches the farmer's loan record.

The outcome

What shipped, when

WhenMilestone
Feb 2021Requirements agreed: Buy Goods collection, USSD access, ledger validation before collection
Feb 2022First live M-Pesa transaction in production
Mar 2022Decision to consolidate three deployment charts into one base chart
Jul 2022Paybill payments with external validation designed for Kenya
Oct 2022Immutable release tags and a published release checklist
May 2023Hotfix releases for amount handling in the loan-system connectors
Nov 2023Payouts discovery: bulk disbursement, account lookup, name-to-number validation
Apr 2024Event-persistence reliability work on the reporting pipeline
Aug 2024OAF delivery patterns turned into templates for new programmes

How it worked

Farmer dials USSD
  └─► USSD gateway (SMS confirmations)
        └─► Payment Hub
              ├─► Loan system: validate      (is this a real, open loan?)
              ├─► M-Pesa: collect            (farmer confirms on handset)
              ◄── M-Pesa callback: success or failure
              └─► Loan system: post repayment

Connectors for M-Pesa and OAF's two loan systems (Paygops and Roster) plug into the same open-source hub, so validate, collect and post is one orchestrated BPMN flow rather than custom code per system. The payloads carried country, currency and wallet-operator fields from day one, so the design wasn't Kenya-only.

Payment Hub Zeebe workflow record M-Pesa Safaricom's record Loan ledger Paygops / Roster every repayment must agree on all three records
Reconciliation is three-way. The workflow engine, Safaricom and the loan ledger each hold a record of the same repayment, so external IDs, amount types and error capture are correctness issues, not cosmetics.

That is why the hotfixes in May 2023 were about amount handling in the loan-system connectors: a repayment that posts with the wrong amount type agrees with M-Pesa on the handset and disagrees in the ledger, and the mismatch surfaces at reconciliation or, worse, on a farmer's loan record.

Tradeoffs worth keeping

What I would do differently

← All case studies