Engineering

Why Your Till Shouldn't Wait a Second and a Half

Jokoor · 10 September 2026 · 6 min read
Database round trip, per query
90ms
Before, across continents
<1ms
After, same private network
~90x
Faster, every query

A shopkeeper in Serrekunda taps a customer's card. A market trader in Kuntaya waits for a mobile money confirmation before handing over change. A boutique in Kanifing watches a checkout page load, and load, and load. In every one of these moments, the person standing at the till is waiting on a string of small decisions happening somewhere else: is the card valid, is the balance enough, did the payment actually clear. None of that thinking is visible. All the customer sees is how long it takes.

That pause, between the tap and the receipt, is where trust in a payment system is either built or spent. And it turns out that pause has very little to do with the payment network itself. Most of it comes down to something far less glamorous: where the database lives.

The cost of distance

For a long time, our database sat in Europe while the servers running our application sat somewhere else entirely. Every query, a lookup, a write, a status check, had to travel that distance and back before it could return an answer. On its own, that round trip cost about 90 milliseconds. Not 90 milliseconds of computer thinking. Ninety milliseconds of pure travel time, the physical cost of a signal crossing continents and coming home.

A single query rarely tells the whole story. A typical request into a payments system touches the database more than once: look up the merchant, look up the customer, check the balance, record the transaction, update the ledger, log the event, confirm the result. A request that makes even seven of those trips was burning more than 600 milliseconds on travel alone, before a single byte of real processing happened. Add the mobile network hop to the customer's phone and the checkout page itself, and a transaction that should feel instant was creeping toward a second and a half.

None of that was visible to a shopper standing at a till. It showed up only as the gap between tapping a card and the screen confirming the sale, the exact moment a queue either keeps moving or starts to stall.

Why this matters more here than almost anywhere

Payments in The Gambia rarely happen over fibre. They happen over mobile data, often patchy mobile data, at a till in a market stall or a small shop with a queue building behind whoever is currently paying. A connection like that is already working hard just to move a checkout page back and forth. Every extra millisecond our own infrastructure adds gets stacked directly on top of that. A market till cannot afford to make a customer wait a second and a half for a page to respond. At that point the problem isn't a slow app, it's a queue that isn't moving and a trader who has to reassure a customer that the payment really did go through.

So the fix was never going to be a cleverer query, or a faster checkout page, or more caching bolted on somewhere. The bottleneck was never the code. It was distance.

Bringing the database home

We moved the database onto our own infrastructure, inside the same private network as the application that actually talks to it. Same query, same read, same write, same amount of real work being done. The only thing that changed was the distance a request had to travel to get an answer. That 90 millisecond round trip to another continent is now under 1 millisecond. Roughly 90 times faster, on every single query, not just the slow ones.

Multiply that across a request that makes several database calls in a row, and the difference stops being a rounding error and starts being most of the response time. The payment logic didn't get smarter. The database didn't get more powerful. It just stopped being far away.

Speed without durability is a gamble

Fast is not the same as safe, and for a company that holds records of other people's money, safe has to come first. We back up the database every 30 minutes to offsite object storage, away from the infrastructure that runs day to day. That part is fairly ordinary. What matters more is the second half of the discipline: we test the restore, regularly and on purpose, not only when something has already gone wrong.

A backup that has never been restored is not a backup. It is a hope, sitting untested until the one day you actually need it, which is exactly the wrong time to discover it doesn't work. Testing the restore turns that hope into a fact we can rely on, and it means the steps for recovering data are already familiar long before anyone is under pressure to use them.

The bug that matters most in this business

There is one category of fault that a payments company has to take more seriously than almost any other: a payment that succeeds with the provider, meaning money genuinely moved, but is not fully recorded on our own side. Left unnoticed, that kind of mismatch can mean a merchant doesn't get credited for a sale they made, or that reconciliation at the end of the month turns into a hunt through logs trying to explain a gap that shouldn't exist. A gap like that doesn't announce itself. It hides until someone goes looking for it, which is exactly why it has to be checked automatically rather than found by accident.

So every 10 minutes, an automated watchdog checks that every completed payment is fully recorded, no exceptions, on a fixed clock, around the clock. Not assumed. Checked. If a payment and our record of it ever fall out of step, we know within minutes rather than at month end, when a trader calls asking why a payment on their statement doesn't match what they saw at the till. It is one of the least visible pieces of engineering behind Jokoor, and exactly the kind of piece that decides whether a fintech has earned the word "trust" next to its name.

Why we're telling you this

Most of what keeps payment infrastructure reliable is invisible on purpose. If a merchant ever notices the database, the backups, or the reconciliation checks directly, something has already gone wrong. That leaves a business with very little to go on when deciding who to trust with its payments, beyond simply watching whether things break.

We would rather explain the actual engineering than let it stay invisible: bringing the database physically close to the code that uses it, testing every backup instead of trusting it blindly, and watching every completed payment until it is confirmed twice, once with the provider and once in our own records. None of that is a feature you can put in a screenshot. All of it is the reason a receipt prints when it's supposed to.

What it means at the till

For a trader in Kuntaya, a shopkeeper in Serrekunda, or a boutique owner in Kanifing, none of this shows up as a headline. It shows up as a receipt that prints a beat faster than it used to, and a bank statement at the end of the month that actually matches what happened during it. That has always been the only measure that really matters, and it is the one we built all of this to get right.

If you're weighing whether to move your business's payments onto Jokoor, this is the infrastructure that will be sitting underneath every transaction. Talk to us, or see what Jokoor Pay looks like for a business like yours.