Digital Wallet Development: Architecture, Ledgers and Licensing Questions
Founder & Lead Engineer, RAITHub
A digital wallet is a ledger with a user interface: every balance is the sum of immutable entries, money enters through top-ups and leaves through payouts, and identity checks gate both. A closed-loop wallet, spendable only inside your product, is typically a 6–12 week backend build. An open-loop wallet that holds customer money usually needs a licensed e-money, payments or banking partner before any code ships.
If you would rather have it built for you, see how RAITHub would build this below.
This guide covers the two wallet types, the licensing questions to take to your adviser in each region, the architecture (ledger, top-up, payouts, KYC, limits, monitoring rules, reconciliation), and an honest buy-or-build comparison. It sits under the payments engineering pillar; the service overview is on the FinTech page.
What is the difference between a closed-loop and an open-loop wallet?
A closed-loop wallet holds value that can only be spent with the business that issued it: store credit, prepaid ride credit, in-app tokens for a tutoring platform. An open-loop wallet holds value the user can spend with many merchants, send to other people or withdraw to a bank account. The difference decides almost everything else, including whether you need a licence.
| Question | Closed-loop wallet | Open-loop wallet |
|---|---|---|
| Where can the balance be spent? | Only with you | With other merchants, other users, or withdrawn as cash |
| Typical examples | Store credit, prepaid usage credits, gift balances | Mobile money, peer-to-peer transfer apps, multi-merchant e-wallets |
| Whose money sits in the wallet? | Often prepaid revenue for your business (ask your accountant) | The customer's money, usually safeguarded by a licensed entity |
| Licensing exposure | Lower, but not zero; some regimes still regulate prepaid value | High in most markets; usually needs a licence or a licensed partner |
| Engineering core | Ledger, top-up, spend, refund, expiry rules | All of that plus KYC, payouts, transfers, limits, monitoring and partner reconciliation |
Many products that say "wallet" actually need a closed-loop balance plus payouts to sellers. Marketplaces are the common case, and there a payment platform's connected-accounts product often does the regulated part for you; see Stripe Connect for marketplace payments.
Do I need a licence to build a digital wallet?
Possibly, and it depends on what the wallet does, where your users are and who holds the money. Building the software is not usually the regulated act; issuing stored value, holding customer funds and transmitting money often are. Below are the questions to take to an adviser in each region, not answers.
- United States. FinCEN's money services business definition covers money transmitters and states that "no activity threshold applies" to them. Individual states also license money transmission. Ask your adviser whether your wallet is money transmission or prepaid access, and which state licences, if any, apply.
- United Kingdom. The FCA authorises and registers electronic money institutions under the Electronic Money Regulations 2011 and the Payment Services Regulations 2017. Ask whether your balance is e-money, and whether any exclusion could apply to a closed-loop design.
- European Union. E-money is governed by the E-Money Directive (2009/110/EC) as implemented in each member state. Ask whether a limited-network exclusion could cover your closed-loop wallet, and what notification it would require.
- Bangladesh. Mobile financial services are overseen by Bangladesh Bank, whose MFS statistics page lists 13 banks providing them. Ask whether your model needs your own approval or a partnership with an existing MFS provider or bank.
Most startups do not get their own licence first. They partner with a licensed entity: an e-money institution or payment service provider that holds the funds, or a bank through a banking-as-a-service (BaaS) programme. Your software then becomes the product layer on top of their regulated accounts, and the partner's own compliance requirements shape your KYC, limits and reporting.
General information; confirm with your adviser. This is engineering guidance, not legal or regulatory advice. RAITHub holds no licences and does not interpret regulation. Whether your wallet needs a licence, an exclusion or a partner is a question for a qualified lawyer or compliance adviser in each market you serve.
What does a digital wallet architecture look like?
Seven components, each with one job. The ledger is the centre; everything else either writes to it through one function or reads from it.
| Component | What it does | The decision that matters |
|---|---|---|
| Ledger | Records every movement as balanced, immutable double-entry postings | Integer minor units; corrections by reversal, never by edit |
| Top-up | Moves money in from a card, bank or mobile-money provider | Credit the wallet only on a verified, idempotent confirmation |
| Spend and transfer | Moves value between wallets or to a merchant | Check balance and limits inside the same database transaction as the posting |
| Payouts | Moves money out to a bank account or mobile wallet | Hold funds in a pending account until the provider confirms the payout |
| KYC via a vendor | Verifies identity before limits rise | Store verification state and evidence references, not raw documents where you can avoid it |
| Limits and monitoring rules | Caps per transaction, per day and per verification tier; flags unusual patterns for review | Rules come from your licensed partner or compliance adviser; engineering makes them configurable and auditable |
| Reconciliation | Matches your ledger against partner and provider settlement reports | A daily job and an exceptions queue a named person owns |
Two rules hold the design together. First, no balance column is ever updated directly; balances are derived from ledger postings or maintained only by the posting function. Second, every write that moves money carries an idempotency key, so a retried request cannot move money twice. The pattern is explained in idempotency in API design.
How should a wallet store balances?
As a double-entry ledger. Each user wallet is an account, and so are the accounts on your side: a clearing account for each provider, a pending-payout account, a fees account. A top-up debits the provider clearing account and credits the user's wallet. A payout debits the wallet, credits pending-payout, and later moves pending-payout to the provider clearing account when the bank confirms.
Because every transaction sums to zero, the total of all accounts is always zero, and any gap is a bug you can find with one query. Store amounts as integers in minor units (cents, poisha) with a currency code on every account, never as floating-point numbers. If a wallet supports several currencies, give each currency its own account rather than mixing them in one balance.
How do top-ups and payouts work without losing money?
Treat the provider's confirmation as the only trigger that moves money, record it under the provider's transaction ID with a unique constraint, and post the ledger entry in the same database transaction. A minimal top-up handler in TypeScript with node-postgres looks like this:
import type { Pool } from 'pg'
type TopUp = { providerTxnId: string; walletAccountId: string; amountMinor: bigint; currency: string }
// Called only after the provider's webhook signature or status API has been verified.
export async function creditTopUp(db: Pool, t: TopUp): Promise<'credited' | 'duplicate'> {
const client = await db.connect()
try {
await client.query('BEGIN')
const seen = await client.query(
'INSERT INTO topups (provider_txn_id, wallet_account_id, amount_minor, currency) VALUES ($1, $2, $3, $4) ON CONFLICT (provider_txn_id) DO NOTHING RETURNING id',
[t.providerTxnId, t.walletAccountId, t.amountMinor.toString(), t.currency],
)
if (seen.rowCount === 0) {
await client.query('ROLLBACK')
return 'duplicate' // the same confirmation arrived twice
}
const clearing = 'clearing:' + t.currency
await client.query(
'SELECT post_transfer($1, $2, $3, $4, $5)',
[clearing, t.walletAccountId, t.amountMinor.toString(), t.currency, 'topup:' + t.providerTxnId],
)
await client.query('COMMIT')
return 'credited'
} catch (err) {
await client.query('ROLLBACK')
throw err
} finally {
client.release()
}
}
Here post_transfer is a database function that writes one balanced journal entry and rejects it if debits and credits differ. Payouts run the other way, with one extra state: the money sits in a pending-payout account until the provider confirms success, and a failed payout is reversed with a new entry, not deleted. Late, duplicate and out-of-order webhooks are covered in testing payments and webhooks.
How does KYC fit into a wallet?
Through a verification vendor, with tiers. A typical design lets an unverified user hold a small closed-loop balance, and raises top-up, transfer and withdrawal limits only as the user completes verification steps. Your licensed partner usually specifies the tiers.
Vendors price per check. Sumsub's public pricing, for example, lists $1.35 per verification with a $149 monthly minimum on its Basic plan, and $1.85 with a $299 minimum on its Compliance plan. The engineering around the vendor is yours: verification states, webhooks from the vendor, retries, a manual review queue, re-verification triggers, retention rules and an audit trail of each decision. An append-only audit log design is in SaaS audit log design.
Buy, build or hire?
Buy when a platform already holds the regulated money for you. Build when the wallet is a core part of your product and your partner gives you an API to build on. Here is the honest comparison.
| Option | Example and published pricing | Choose this when | Watch out for |
|---|---|---|---|
| Off-the-shelf payments platform | Stripe Connect: no platform fee when Stripe handles pricing, or $2 per monthly active account plus 0.25% + 25¢ per payout when you handle pricing | You need seller balances and payouts in a marketplace, in countries the platform supports | Balances live in the provider's system; you cannot add peer-to-peer transfers or stored value it does not support |
| Configured billing credits (no custom ledger) | Stripe Billing: 0.7% of billing volume on pay-as-you-go, with a customer balance and prepaid credit features | Your "wallet" is prepaid credit for your own SaaS or service, never withdrawn or transferred | Not a wallet users can send or cash out; limited reporting for complex rules |
| Custom build on a licensed partner | Your own ledger, top-up, payouts and KYC over a partner's regulated accounts; partner and KYC fees are quoted by each vendor | The wallet is your product, or you need rules, rails or markets no platform covers | The longest path: partner onboarding, compliance review and reconciliation are on the critical path, not only the code |
How long does a wallet take to build yourself?
For an experienced backend team, a closed-loop wallet (ledger, top-up through one provider, spend, refunds, admin view and reconciliation report) is roughly 6–10 weeks. An open-loop wallet on a partner adds KYC tiers, payouts, transfers, limits and partner reconciliation, and the calendar is usually set by partner onboarding rather than code.
The main risk of doing it yourself is a ledger that is "nearly right": a balance column updated in two places, a retry that credits twice, or a reversal that edits history. Those bugs do not show up in demos. They show up weeks later as a reconciliation gap nobody can explain. Test them deliberately: replay every webhook, run concurrent spends against one balance, and assert that the sum of all accounts is zero after each test.
Why RAITHub for this
RAITHub is a founder-led software studio, founded in 2024 in Dhaka, Bangladesh, working with clients worldwide in English. For wallets, the relevant proof is payment and money engineering, not a shipped wallet.
- Mobile-money rails in production. TheSkinProof, the founder's own venture, takes bKash, Nagad, SSLCommerz and cash on delivery across 217 API endpoints with 750+ automated tests. That is payment acceptance in a marketplace, not a wallet: it does not hold stored value for users. The integration notes are in the bKash and SSLCommerz integration guide.
- Money modelled correctly. Sundor Skin stores amounts as integer minor units, enforces credit limits in the database and keeps a hash-chained audit log, under 530+ automated tests.
- Many rails behind one abstraction. PadhAI was built for 9 payment gateways behind one interface.
- Fintech client work. RAITHub's 8 client projects include a fintech dashboard.
- How data is handled. We sign NDAs and DPAs and work inside your controls; production and financial data stay in your own cloud account; development uses synthetic data.
When you don't need us
- Your wallet is really marketplace payouts. A connected-accounts product such as Stripe Connect may cover it with configuration, not a build.
- Your wallet is prepaid credit for your own service. Your billing platform's credit features may be enough.
- You need a vendor that has shipped a licensed wallet. RAITHub has shipped no regulated or licensed fintech product. If your partner bank or investors require that track record, hire a firm that has it and ask to speak to that client.
- You have no licensing answer yet. Get your adviser's view and a partner shortlist first. Code written before that often has to change.
How RAITHub would build this
- Ledger first: a PostgreSQL double-entry ledger with balanced-entry enforcement, integer minor units, idempotency keys and reversal-only corrections.
- Money in and out: top-up and payout integrations with your chosen provider or licensed partner, verified webhooks and a status-polling fallback.
- Identity and limits: KYC through your chosen vendor, verification tiers, configurable limits and a review queue, using the rules your partner and adviser define.
- Reconciliation and admin: daily settlement import, matching, an exceptions queue and an audited admin console.
- Web app or PWA: the user-facing wallet as a responsive web app or PWA. RAITHub does not build native mobile apps.
Timeline: as a backend and API engagement, typically 6–12 weeks, depending on how many rails you need and how fast your partner's sandbox and onboarding move. A narrow closed-loop MVP with fixed scope can fit the 4–6 week MVP range.
What you receive: automated tests and CI on every change, including replayed-webhook, concurrency and zero-sum ledger tests; handover documentation and runbooks for reconciliation exceptions and stuck payouts; and full IP ownership under NDA. See Backend and API development for how the engagement runs, and our work for the platforms named above.
Next step: book the free 15-minute technical audit. Bring your wallet type, markets, licensed partner (or shortlist) and your adviser's view. You get a written fixed quote afterwards, with compliance, licensing and partner fees listed as yours to budget.
Frequently asked questions
What is the difference between a closed-loop and an open-loop digital wallet?
A closed-loop wallet holds value spendable only with the business that issued it, such as store credit. An open-loop wallet can be spent with other merchants, sent to other users or withdrawn, which usually brings licensing questions.
Do I need an e-money or money transmitter licence for a wallet?
It depends on what the wallet does and where your users are. Many startups partner with a licensed e-money institution, payment provider or bank instead of getting their own licence. This is general information; confirm with your adviser.
Has RAITHub built a licensed digital wallet?
No. RAITHub has shipped no regulated or licensed fintech product. It has shipped bKash, Nagad and SSLCommerz payment acceptance in TheSkinProof, the founder's own venture, and its client work includes a fintech dashboard.
How should a wallet store balances?
In a double-entry ledger with amounts as integer minor units. Balances come from immutable postings, every transaction sums to zero, and corrections are new reversing entries, never edits.
How much does KYC cost for a wallet?
Vendors charge per verification. Sumsub's public pricing lists $1.35 per verification with a $149 monthly minimum on its Basic plan. The engineering around the vendor, such as states, review queues and audit trails, is a separate cost.
Can RAITHub build a mobile wallet app?
RAITHub builds the backend and a web app or PWA, not native iOS or Android apps. A PWA can be installed on a phone's home screen and works well for many wallet use cases.
How long does it take to build a digital wallet?
A closed-loop wallet is roughly 6–10 weeks of backend work for an experienced team. An open-loop wallet usually waits on partner onboarding and compliance review, which set the calendar more than the code does.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.