Back to FintelliHubPayments

Designing payments for unreliable networks

Offline-first isn't a feature in African fintech — it's the baseline. What we learned building a point of sale that keeps selling through power and network outages.

By Fintellisys team#payments#offline-first#pos#resilience
Designing payments for unreliable networks

Most payment software is written by people with good internet. You can tell, because it treats the network as present by default and absent as an error state — a spinner, a toast, a retry button. That model works fine until the shop you built it for loses connectivity for six hours on a Saturday, which is the single busiest trading window of the week.

We build for the opposite assumption. The network is absent by default and present opportunistically. Everything the till needs to complete a sale lives on the device: the product catalogue, prices, tax rules, the current stock position, the operator's permissions. A sale is written locally, confirmed to the customer immediately, and queued. Synchronisation is a background concern that the cashier never waits for and, ideally, never thinks about.

That inversion sounds obvious written down. In practice it changes almost every design decision downstream.

It changes what an identifier is. If the server assigns receipt numbers, an offline till cannot produce a receipt, and a receipt is not optional — it is often a legal requirement. So identifiers get generated at the edge, with enough entropy and enough device-specific prefix that two tills in the same shop cannot collide even if neither has spoken to the server in a day.

It changes what a total means. A sale computed offline must produce exactly the same figure when the server re-computes it later. That means tax and discount rules cannot live only in the backend. They must be versioned, pushed to devices, and applied identically on both sides — and when a rule changes mid-day, the sale has to record which version it used. Otherwise reconciliation becomes an argument nobody can win.

It changes what "confirmed" means to a customer. There is a real difference between a sale the merchant has recorded and a payment the issuer has authorised. Cash and mobile money settled outside the system can be confirmed instantly offline. Card authorisation genuinely cannot. Pretending otherwise doesn't make the network appear; it just moves the failure to somewhere more expensive. The interface has to be honest about which of those two things has happened, in language a cashier can repeat to a queue.

It changes what you store. Six hours of offline trading on a busy till is a lot of rows, and the device is often a low-end Android tablet with a full storage partition and no thermal headroom. Queued transactions have to be compact, written durably enough to survive an abrupt power cut mid-write, and pruned once acknowledged. We have lost more data to unclean shutdowns than to network failures.

And it changes what you do about power. Connectivity and electricity fail together more often than not, because the tower and the shop are on the same grid. A design that survives network loss but assumes the tablet stays charged has solved half the problem. Battery-first hardware, aggressive screen management and a fast cold-start path matter as much as any sync algorithm.

The hardest part is none of this. The hardest part is what happens when the connection returns and the server discovers that the world moved while it wasn't looking — two devices that both sold the last unit of stock, a price that changed centrally during an outage, a refund processed against a sale the server has never seen. That is a genuinely difficult class of problem and it deserves its own discussion.

What we would say to anyone building in this space: stop treating the outage as the exception. In most of the markets we work in, it is a scheduled part of the week. Software that treats a normal Tuesday as an error condition will be worked around, and the workaround will be a paper notebook that never gets keyed in.

Build for the notebook. Then you don't need it.