DEV Community

Cover image for I am building a NestJS ledger designed so money can move a thousand times a second without ever vanishing
Peace Melodi
Peace Melodi

Posted on

I am building a NestJS ledger designed so money can move a thousand times a second without ever vanishing

Most systems that handle money keep things simple, a single balance number sitting on an account record. Money comes in, the number rises. Money goes out, the number falls. This works fine right up until two requests touch that same number within the same fraction of a second, or until someone needs to know exactly what happened to an account months earlier and finds nothing but today's number staring back, no trail, no context, no way to prove anything actually happened the way it was claimed.

I am building a ledger that rejects this approach entirely. The goal is easy to state and genuinely hard to achieve, money should be able to move through the system a thousand times a second under real concurrent pressure, and it should be structurally impossible for even one dollar to quietly vanish, get counted twice, or get silently rewritten. Here is what that actually looks like underneath, and how NestJS is helping turn it into something real.

Replacing a balance with a history

The first major decision was abandoning the balance column altogether. Rather than one number that gets overwritten each time something happens, every movement of funds becomes its own permanent, untouchable entry. Nothing is ever updated. Nothing is ever deleted. When a mistake happens, a correcting entry gets appended, and the original stays exactly where it was, permanently part of the record.

A balance is no longer something the system keeps in storage. It becomes something the system works out, by totaling every credit and subtracting every debit tied to that account. This one shift is what keeps the entire ledger trustworthy. There is no back door where a bug or a hurried patch can silently overwrite what genuinely occurred.

Every movement is a pair, never a single entry

Real bookkeeping does not allow money to simply appear or vanish, it only moves from one place to another. So every transaction here writes two entries simultaneously, a debit against one account and a credit against another, both required to exist together inside a single atomic database transaction.

Should either entry fail to save for any reason, the entire transaction rolls back and neither one exists. There is no scenario in this system where funds leave one account without landing somewhere else, because both entries are bound to succeed or fail as one unit.

Keeping a thousand requests a second from colliding

Getting the history right solves honesty. It does not automatically solve speed once real concurrent pressure enters the picture. If a thousand transfer requests hit the same account within a short window, something needs to stop two of them from both acting on an outdated balance and approving a transfer that should never have gone through. This is handled with a database level lock at the exact moment an account is read for a transfer.

Once a request holds this lock, every other request aimed at the same account has to wait its turn. Nobody gets to act on a stale number, because the database itself will not let a second request read anything until the first one has fully committed its change.

Turning the danger into something you can actually watch happen

Describing a race condition in words only carries a message so far. Alongside the real API, I am building a small live control panel served directly from within the NestJS app, where two transfer requests can be fired at the exact same account, at the exact same moment, on demand. Watching the lock genuinely force the second request to queue and wait, in real time, makes the whole problem tangible in a way reading about it never quite achieves.


Triggering this twice at once against the same account demonstrates exactly what the lock defends against, one request goes through cleanly, and the other either waits and then succeeds against the freshly updated balance, or correctly fails if the funds are no longer available.

The bigger picture

None of this is about clever code for its own sake. Every choice here exists to answer one honest question, if a thousand people tried to move money through this system in the exact same second, could a single dollar end up in the wrong place, or disappear entirely. Permanent entries instead of a balance column, paired debits and credits inside one atomic transaction, and row level locking at the exact point where contention happens, together these three things are what keep that answer at no, even under genuine pressure, not just inside a quiet, empty test environment.

This project is still under active construction, with more still to come, idempotency keys to guard against retried requests, and a proper reconciliation layer to surface anything unexpected over time. But the foundation, the part that has to be solid before anything else matters, is already standing firm.

If you are building anything where money, or any value that genuinely cannot afford to quietly disappear, flows through your backend, this is exactly the kind of groundwork I care about getting right.

I am Peace Melodi, a backend software engineer. If you want your business to scale big, comfortably handling millions of users without breaking, with strong scalability and security in place, feel free to reach out.

LinkedIn: https://www.linkedin.com/in/melodi-peace-406494368
GitHub: https://github.com/PeaceMelodi

Top comments (0)