Tech Blog
Designing a multi-rail payments gateway: lessons from 15+ integrations
Every payment rail has its own quirks. The trick is hiding them behind one clean interface.
Marichi Labs Engineering · · 7 min read
One interface, many rails
Mobile money, cards and bank transfers differ in flow, timing and failure modes. A gateway should expose one consistent model of a payment, and translate it for each rail.
Idempotency is not optional
Networks fail and clients retry. Every payment request needs an idempotency key so a retry never charges twice.
Treat webhooks as unreliable
Callbacks arrive late, twice or not at all. Verify signatures, process them idempotently and run a reconciliation job that checks status directly.
Reconciliation as a first-class feature
Reconciliation is not an afterthought. Storing every state change as an append-only ledger makes audits and debugging straightforward.