STK Push looks deceptively simple in the Daraja docs — one POST, one callback, done. In production, you discover the rough edges fast: callbacks that fire twice, customers who time out their PIN entry, reversals that arrive days later, and reconciliation gaps that hide in plain sight.
Over the last three years we've shipped M-Pesa integrations for clinics, schools, retailers and SACCOs. This is the architecture we now default to: an outbox table for every initiated push, idempotent callback handlers keyed by CheckoutRequestID, a reconciliation worker that polls the C2B confirmation endpoint, and a settlement view that joins to your bank statement.
The single biggest win is treating the callback as advisory, not authoritative. The truth lives in the bank reconciliation. When you internalize that, your finance team stops chasing ghosts and your support tickets drop by 60%+.