Almost every business we work with in Kenya eventually needs Mpesa integrated somewhere: a booking platform, a fintech ledger, an internal payments dashboard. The Daraja API sandbox makes it look like an afternoon's work. Production traffic tells a different story.
The failure modes that don't show up in testing
- STK push callbacks that never arrive, or arrive twice, and need idempotent handling
- Timeouts on Safaricom's side that leave a transaction in limbo until it's reconciled
- Customers closing the prompt or losing signal mid-payment, with no clean way to know the outcome
- Reconciliation between what your system recorded and what Safaricom actually settled
None of these are exotic edge cases. They're what a real customer base produces at volume. A system that hasn't been built to expect them will eventually show a customer "payment failed" for a payment that actually went through, or worse, the reverse.
More on how we build for fintech & banking →
Build for reconciliation from day one
The integrations that hold up under real usage treat the callback as one signal among several, not the source of truth. That means a reconciliation job that checks transaction status directly, idempotency keys that prevent double-processing, and clear operator visibility when something needs a human to look at it. It's more work upfront. It's much less work at 11pm when a customer says they paid and your system says they didn't.