What Makes Digital Wallet Development Harder Than It Looks
By Maplecode
A wallet screen is not difficult to build. A balance, a top-up button, a transaction list, a send flow. A competent mobile developer produces something convincing in a fortnight, which is why so many wallet projects begin with optimistic estimates.
What follows is the part nobody scoped. Holding a customer's money is a regulated activity in most jurisdictions, the failure cases dominate real traffic, and the accounting has to survive an auditor who does not care how good the interface is. This is a walk through the parts that reliably turn a two-month estimate into a year.
Deciding whether you are holding money at all
The first question is not technical. If customer funds sit in a balance you control, you are probably conducting a regulated activity — issuing electronic money, operating a payment service, or something with a local name and a licensing regime attached. The thresholds and definitions differ by jurisdiction, and getting this wrong is not a bug you patch later.
There are architectures that avoid it. A wallet that stores a tokenised card and charges it per transaction never holds a balance. A closed-loop wallet usable only with the issuing merchant often sits in a lighter category. A wallet holding a general-purpose balance that can be sent to other users is the heaviest option, and it is the one most product teams sketch first because it demos best.
This decision determines your licensing, your capital requirements, your safeguarding obligations and a good deal of your architecture. It should be settled with counsel before anyone designs a schema, and it is worth understanding that a product decision made for user experience reasons can quietly change your regulatory category.
The ledger is the product
The most common serious defect we see in wallet systems is a balance stored as a mutable number on a user record. It is the obvious design and it is close to unrecoverable when something goes wrong, because when the number is incorrect there is no way to establish what it should have been.
What works is double-entry accounting: an append-only ledger of entries that each reference an account and an amount, with the balance derived by summing them. Nothing is ever updated in place. A correction is a new entry, not an edit. The balance becomes a computed view, which can be cached for performance but is always reconstructable from the entries.
This buys you the ability to answer questions you will definitely be asked. Why is this balance what it is. What was it on the third of March. Which entry was wrong. An auditor asking about a discrepancy from six months ago is a routine query rather than a forensic exercise.
Two details matter more than they appear. Store money as integers in the smallest currency unit — a floating-point balance will eventually be wrong by a fraction of a cent, and in aggregate that becomes a reconciliation break. And give every entry an idempotency key derived from the originating event, so a retried request cannot produce a duplicate entry.
Partial failure is the normal case
A top-up involves your system, a payment processor, a card network and an issuing bank. Any of them can time out, and a timeout is not a failure — it is an unknown outcome. The payment may have succeeded. The callback may arrive in four minutes, or tomorrow, or twice.
Systems designed around the success path handle this by guessing, and the guesses are expensive in both directions. Assume failure and you have taken the customer's money without crediting it. Assume success and you have credited a balance the customer never funded.
The workable pattern is to treat a payment as a state machine with an explicit pending state, and to reconcile against the processor rather than trusting callbacks. Callbacks are a latency optimisation; the authoritative answer comes from querying the processor for the transaction's status. A scheduled reconciliation that compares your pending entries against the processor's records catches everything the callbacks missed, and it needs to run frequently enough that a customer is not waiting on it.
Disputes and reversals shape the schema
Money can come back. A card top-up can be charged back weeks later. A transfer can be reversed. A merchant refund can arrive after the customer has already spent the balance elsewhere, which leaves an account negative and a policy question about who absorbs it.
Retrofitting this is where wallet projects lose months. Reversals are not deletions — the original entry stays and a compensating entry is added, because the history of what happened is itself information you need. That means the schema has to accommodate linked entries, and the balance calculation has to account for holds and pending reversals rather than just settled amounts.
Where the security work actually is
Most wallet security attention goes to the login. That matters, but account takeover in wallets more often runs through account recovery, and through the support process. A password reset flow that verifies a phone number is only as strong as your resistance to SIM swap. A support agent who can change a registered device is an attack surface with a salary.
The controls that pay for themselves are unglamorous: velocity limits per account and per device, a hold period on funds after a device or contact change, step-up authentication tied to transaction value rather than applied uniformly, and an audit trail of every support action taken on an account. Fraud in wallets is usually a process failure rather than a cryptographic one.
What a realistic plan looks like
The regulatory position comes first, because it constrains everything after it. Then the ledger, because retrofitting double-entry accounting onto a system with live balances is a migration nobody enjoys. Then one funding method end to end, including its reconciliation and its dispute path, before adding a second. Then the interface, which is genuinely the part that goes quickly.
Teams that sequence it the other way — interface first, ledger later, compliance in parallel — usually end up rebuilding the middle. If you are weighing this up, our note on build versus buy is worth reading first: for a general-purpose wallet, a licensed provider handling the balance and the compliance is very often the better commercial answer, and the interesting engineering is then in what you build on top.