Kennedy Wambua
← All posts
By Kennedy Wambua · · 2 min read

A balance is a rule, not a number

Why Mintfa keeps payment amounts in integer minor units and makes the database reject impossible balances.

When a product shows someone a balance, it is answering a practical question: how much can I use right now?

That answer is easy to display and surprisingly easy to get wrong. A single mutable balance field hides how the number was reached. A payment may still be pending. Some money may be held or reserved. If those states get mixed together, two parts of an application can disagree about what is available.

Start with amounts that add up

Mintfa stores money as integer minor units. Floating-point values are useful for many calculations, but money needs exact arithmetic: a ledger that drifts by even one cent is wrong.

Every ledger journal must balance. Value leaving one account has to appear somewhere else in the same journal. The database checks that invariant, so it does not depend on every API handler remembering to do the right thing.

For a wallet, the available balance follows an explicit rule:

available = posted - pending - held - reserved

The buckets make the calculation explainable. Pending, held and reserved amounts are visible parts of the model, not adjustments hidden in a hand-edited total.

Put the rule where all writes meet

Application code can have bugs, and products gain new code paths over time. If the only balance check lives in one service method, another worker or future endpoint can bypass it.

Database constraints give each write the same boundary. The application still needs good validation and clear errors, but the database has the final say on whether a journal balances and a wallet state is possible.

The same idea affects transactions. Mintfa writes the payment, ledger change and outbox event together in PostgreSQL. A worker delivers the webhook after that transaction commits. That keeps the event tied to the state change it describes.

Concurrency tests matter for the same reason. Two requests can arrive close together and both look at the same available amount. The system has to preserve the invariant under competing writes, not just when requests happen one at a time.

What I want the number to mean

The interface should be able to show a balance without inventing accounting rules of its own. The ledger defines the states, the database protects the arithmetic, and the API reports the result.

Mintfa is still in development and tested against the M-Pesa sandbox; live payments are not open yet. The design is not proven by real traffic. But making the rules explicit gives us something precise to test before money depends on them.